查看原文
其他

Unix 中的 I/O 模型

Linux爱好者 2019-05-07

(给Linux爱好者加星标,提升Linux技能


作者:Pedlar(本文来自作者投稿)

www.cnblogs.com/pedlar/p/10671504.html


一. POSIX对同步、异步I/O的定义


我们先大致看看POSIX对同步、异步的定义,不用细究,重点看我标红的部分就行。


  • 同步I/O会导致请求进程阻塞,直到I/O操作完成;

  • 异步I/O不会导致请求进程阻塞。


二. 同步、异步,阻塞、非阻塞

  

个人理解同步与否与阻塞与否只是看待问题的不同维度,不用过于追究同步和阻塞有什么区别、以及异步和非阻塞有什么区别。

  

我用小明购买火车票的例子大致先讲述下同步、异步,阻塞、非阻塞这几种情况的组合。


  • 同步阻塞,小明去火车站买票。首先,他需要在某一个售票窗口排队,当轮到他买票时,他需要告诉售票员他需要一张去上海的火车票,然后售票员需要去系统查询是否还有余票,有的话再收款出票,最后再把票给小明。在火车票到手之前,小明都不能做其他的事情,这种情况我们可以理解为阻塞。

  • 同步非阻塞,小明委托黄牛帮忙买火车票,然后小明可以做其他事情,但是需要每隔10分钟就打电话去询问黄牛票是否买到。黄牛买到票后,打电话通知小明说票已经买到,小明再去黄牛那里取火车票。这里的非阻塞指的是黄牛在买票的过程中,小明是不用等待的,他可以做其他事情,只是需不时地去询问黄牛票是否买好。但是,在小明去黄牛那里取票的过程中,小明还是不能做其他事情。

  • 异步阻塞,基本上没有这个说法。

  • 异步非阻塞,小明委托黄牛帮忙买火车票,然后小明可以做其他事情,黄牛买好票后会自动把票送到小明的家里。在这整个过程中,小明都可以做他自己想做的事情,不会被阻塞。


三. Unix中的I/O模型

  

OK,有了上面的基础过后,我们可以开始讲I/O模型了。

  

在网络Socket的输入操作中,I/O大致可以分为两个阶段,这个两个阶段大家务必掌握:


    1. 数据从网络中抵达,然后数据被复制到系统内核的缓冲区;

    2. 系统内核将内核缓冲区中的数据复制到用户进程的缓冲区中。

  

在Unix中有5种I/O模型,它们是:


    1. 阻塞式I/O

    2. 非阻塞式I/O

    3. 多路复用I/O

    4. 信号驱动I/O

    5. 异步I/O

  

下面,我们逐一分析每种I/O模型。


1.阻塞式I/O

  

阻塞式I/O,即Blocking I/O。用户发起一个recvfrom系统调用,内核会等待数据从网络中到达。一旦数据准备就绪,系统内核将把自己的缓冲区中的数据拷贝到用户进程的缓冲区。在系统内核等待数据、复制数据的过程中,用户进程是不能做其他任何事情的,只能等待内核完成上述一系列的操作。



2.非阻塞式I/O

  

与阻塞式I/O不同,非阻塞式I/O中,用户进程在发起recvfrom系统调用后可以立即返回,但是用户进程需要不时地循环询问系统内核数据是否已经准备就绪,即轮询(polling)。轮询往往会消耗大量的CPU时间。

  

下图中,用户进程发起recvfrom系统调用,由于系统内核中数据尚未就绪,内核会立即返回EWOULDBLOCK错误码,防止用户进程阻塞。如此往复,直到系统内核中数据准备就绪。在数据就绪前,用户进程是非阻塞的,这也就是为什么这种模型叫非阻塞式I/O的原因。数据就绪后,和阻塞式I/O一样,内核将数据拷贝至用户进程,在数据拷贝的过程中,用户进程是阻塞的。



3.多路复用I/O

  

多路复用I/O的关键函数为select或者poll。我们以select函数为例,当我们调用该函数时,用户进程将阻塞,直到系统内核中的数据准备好。数据就绪后,系统会通知用户进程数据已经可读,然后用户进程会发起recvfrom系统调用,将数据从内核拷贝到用户进程,在数据拷贝期间,用户进程是阻塞的。

  

使用多路复用的优势是我们可以等待多个描述符就绪,对应到Java NIO多路复用模型中就是我们可以使用一个线程监听多个Channel的请求。



4.信号驱动I/O

  

信号驱动I/O模型主要是让内核在描述符就绪的时候发送SIGIO信号通知用户进程,据我的了解,这种I/O模式运用的并不多,这里就不多描述,直接看图吧。



5.异步I/O

  

用户进程在调用异步I/O函数后会立即返回,并且会让内核在完成所有操作后通知用户进程。在内核进行I/O操作的期间,我们的用户进程不会阻塞。特别需要注意的是,和前面四中I/O模型不同,异步I/O模型在内核将数据拷贝到用户进程时,我们的用户进程不会阻塞。

 


四. I/O模型对比

  

对比上述5中I/O模型我们可以发现,前面4种模型的区别主要在第一阶段,而第二阶段都是一样的,即将数据从内核拷贝到用户进程时都会阻塞。根据POSIX对同步、异步I/O的定义,可以得出前4种模型都属于同步I/O。而第5种I/O,即异步I/O,两个阶段的操作都是由系统内核来处理的,用户进程并没有介入。



推荐阅读

(点击标题可跳转阅读)

微软研究员:fork() 成为负担,需要淘汰

VMware 侵权 Linux 源码案原告放弃上诉:没意义

Linux 基础命令:IP 路由操作



看完本文有收获?请分享给更多人

关注「Linux 爱好者」加星标,提升Linux技能

喜欢就点一下「好看」呗~

    您可能也对以下帖子感兴趣

    文章有问题?点此查看未经处理的缓存