分享

unix下的I/O

 lchjczw 2013-03-12

Stevens一共提出了五种 IO Model:

  • blocking IO  
  • nonblocking IO
  • IO multiplexing (select and poll)
  • signal driven IO (SIGIO)
  • asynchronous IO (the POSIX aio_functions)


先说一下IO发生时所涉及的对象和步骤。
一个输入操作通常包括下面两个阶段:
 1 等待数据准备好 (Waiting for the data to be ready)。对于一个套接口上的输入操作,通常涉及等待数据从网络到达,到达后它被拷贝到内核的某个缓冲区。
 2 将数据从内核缓存区拷贝到进程缓冲区中 (Copying the data from the kernel to the process)
记住这两个阶段很重要,因为以下要讨论的五种IO Model的区别就是在两个阶段上各有不同的情况。


Blocking I/O Model(阻塞I/O)

默认情况下所有的套接口都是blocking。

进程调用recvfrom,其系统调用直到数据报到达(第一阶段)且被拷贝到应用进程的缓冲区中(第二阶段)或者发生错误(最常见的错误是系统调用被信号中断)才返回。进程在从调用recvfrom开始到它返回的整个过程是被阻塞的。recvfrom成功返回后,应用进程开始处理数据报。


Nonblocking I/O Model(非阻塞I/O)

前三次调用recvfrom时数据还没准备好,这是内核立即返回一个EWOULDBLOCK错误。第四次调用recvfrom时数据已准备好,它被拷贝到应用进程缓冲区,recvfrom接着成功返回,然后应用进程开始处理数据报。

这里最关键的一个操作就是轮询(polling)。应用进程持续轮询内核,以查看数据是否就绪。这样做往往会耗费大量的CPU时间,这种模型通常会在专门提供某种功能的系统才有。

 

I/O Multiplexing Model(I/O复用模型)

当用户进程调用了select,那么整个进程会被block,而同时,kernel会“监视”所有select负责的socket,当任何一个socket中的数据准备好了,select就会返回套接字可读这个条件,我们调用recvfrom把所读数据报拷贝到应用程序进程缓冲区。

和blocking IO的图比较,I/O复用并没有显示出什么优势。事实上,可能稍有劣势。因为这里需要使用两个system call (select 和 recvfrom),而blocking IO只调用了一个system call。但是,用select的优势在于它可以同时处理多个connection。


Signal-Driven I/O Model(信号驱动I/O模型)

我们首先开启套接口的信号驱动I/O功能,并通过sigaction系统调用安装一个信号处理函数。该系统调用将立即返回,我们的进程这是并没有被阻塞,而是继续执行。当数据报准备好读取时,内核就为该进程产生一个SIGIO信号。我们随后既可以在信号处理函数中调用recvfrom读取数据报,并通知主循环数据已准备好待处理,也可以立即通知主循环,让它来读取数据报。无论如何处理SIGIO信号,这种模型的优势在于等待数据报到达(第一阶段)期间,进程可以继续执行,不被阻塞。

 

Asynchronous I/O Model(异步I/O模型

进程发起read操作之后,立刻就可以开始去做其它的事。而另一方面,从kernel的角度,当它受到一个asynchronous read之后,首先它会立刻返回,所以不会对用户进程产生任何block。然后,kernel会等待数据准备完成,然后将数据拷贝到用户内存,当这一切都完成之后,kernel会给用户进程发送一个signal,告诉它read操作完成了。

这个模型工作机制是:告诉内核启动某个操作,并让内核在整个操作(包括第二阶段,即将数据从内核拷贝到进程缓冲区中)完成后通知我们。

这种模型和前一种模型区别在于:信号驱动I/O是由内核通知我们何时可以启动一个I/O操作,而异步I/O模型是由内核通知我们I/O操作何时完成。



五种I/O模型介绍完了,下面来说说blocking和non-blocking的区别在哪,synchronous IO和asynchronous IO的区别在哪。

blocking I/Ovs non-blocking I/O :调用blocking IO会一直block住对应的进程直到操作完成,而non-blocking IO在kernel还准备数据的情况下会立刻返回。

synchronous I/O vs asynchronous I/O:

先看看这两个定义:

 A synchronous I/O operation causes the requesting process to be blocked until that I/O operation completes;
 An asynchronous I/O operation does not cause the requesting process to be blocked;

两者的区别就在于synchronous IO做”IO operation”的时候会将process阻塞。按照这个定义,之前所述前四种模型blocking I/O,non-blocking I/O,IO multiplexing,signal driven IO都属于synchronous IO。有人可能会说,non-blocking IO并没有被block啊。这里有个非常“狡猾”的地方,定义中所指的”IO operation”是指真实的IO操作,就是例子中的recvfrom这个system call。non-blocking IO在执行recvfrom这个system call的时候,如果kernel的数据没有准备好,这时候不会block进程。但是,当kernel中数据准备好的时候,recvfrom会将数据从kernel拷贝到用户内存中,这个时候(第二阶段)进程是被block了,在这段时间内,进程是被block的。而asynchronous IO则不一样,当进程发起IO 操作之后,就直接返回再也不理睬了,直到kernel发送一个信号,告诉进程说IO完成。在这整个过程中,进程完全没有被block。


各个IO Model的比较如图所示:

 

前4种模型的主要区别在于第一阶段,因为它们的第二阶段都是一样的:在数据从内核缓冲区拷贝到进程缓冲区期间,进程阻塞与recvfrom这个系统调用中。

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多