UNIX五种I/O模型

UNIX的五种I/O模型:阻塞式I/O模型,非阻塞式I/O模型,I/O复用模型,信号驱动式I/O模型,异步I/O模型。这些概念看似容易混淆,从UNIX底层的I/O操作的角度来分析,其实不难理解。

一个输入操作通常包括以下两个阶段:

  1. 等待数据准备好;包括等待数据从网络中到达,数据到达后存入内核的缓冲区中。
  2. 从内核向进程复制数据。把数据从内核缓冲区复制到进程缓冲区。

下面要讲的五种I/O模型实际上就是在这两个阶段中的阻塞策略不同。接下来以UDP的recvfrom为例,进行说明。

阻塞式I/O模型

blocking IO,最直观的I/O模型。应用进程调用recvfrom方法时,会进行阻塞,直到两个阶段都结束,数据复制到进程缓冲区时,方法才返回。成功返回后,应用程序再进行后续工作。流程如下图所示:

image

非阻塞式I/O模型

此种模型下,recvfrom方法可立即返回。若内核数据没有准备好,则返回一个错误;若数据准备好,进行第二阶段复制操作,再返回成功指示。流程如下图所示:

image

该种模型较为少见,因为往往需要应用程序持续轮询内核,看看操作有没有准备就绪。这样会耗费大量CPU时间。

I/O复用模型

I/O复用是生产中最常见的网络模型。调用select或者poll方法去查看内核中数据是否准备好,准备完毕即返回,否则保持阻塞。但是请注意,select调用和recvfrom调用往往不在一个线程中,所以此处的阻塞不会影响真正的IO操作。当套接字可读,select返回,回调执行recvfrom,完成输入操作。如下图所示:

image

如果只是线性地看两个阶段是否有阻塞,IO复用似乎没什么优势。但实际上,使用select的优势在于“多路复用”,即一个selector等待多个文件描述符。

扫描二维码关注公众号,回复: 11254583 查看本文章

信号驱动式I/O模型

信号驱动式I/O模型,先通过sigaction调用安装一个信号处理函数,并立即返回。当套接字可读时,内核发送SIGIO信号通知应用程序,执行recvfrom方法执行IO输入。如下图所示:

image

这种模型,在接收到SIGIO信号之前,进程不会被阻塞。

异步I/O模型

前面四种IO模型,实际上在第二阶段(从内核缓冲区读取数据到用户缓冲区)都是阻塞的。而异步I/O模型在两个阶段都是非阻塞的。即先告知内核启动IO操作,立即返回,在两个阶段(准备数据和读取数据)全部完成时,内核发送信号通知用户进程。如下图所示:
image

各种I/O模型的比较

首先明确两个概念:同步I/O异步I/O,POSIX对其定义如下:

  • 同步I/O(synchronous I/O operation):导致请求进程阻塞,直到IO操作完成;
  • 异步I/O(asynchronous I/O operation):不导致请求进程阻塞。

五种模型的对比如下

image
五种I/O模型中,除了异步I/O,其余四种或多或少都有阻塞的过程。因此,按照POSIX的标准,阻塞式I/O模型、非阻塞式I/O模型、I/O复用模型、信号驱动式I/O模型,都称之为同步I/O。

猜你喜欢

转载自www.cnblogs.com/buptleida/p/12944045.html