UNIX的五种I/O模型:阻塞式I/O模型,非阻塞式I/O模型,I/O复用模型,信号驱动式I/O模型,异步I/O模型。这些概念看似容易混淆,从UNIX底层的I/O操作的角度来分析,其实不难理解。
一个输入操作通常包括以下两个阶段:
下面要讲的五种I/O模型实际上就是在这两个阶段中的阻塞策略不同。接下来以UDP的recvfrom为例,进行说明。
blocking IO,最直观的I/O模型。应用进程调用recvfrom方法时,会进行阻塞,直到两个阶段都结束,数据复制到进程缓冲区时,方法才返回。成功返回后,应用程序再进行后续工作。流程如下图所示:
此种模型下,recvfrom方法可立即返回。若内核数据没有准备好,则返回一个错误;若数据准备好,进行第二阶段复制操作,再返回成功指示。流程如下图所示:
该种模型较为少见,因为往往需要应用程序持续轮询内核,看看操作有没有准备就绪。这样会耗费大量CPU时间。
I/O复用是生产中最常见的网络模型。调用select或者poll方法去查看内核中数据是否准备好,准备完毕即返回,否则保持阻塞。但是请注意,select调用和recvfrom调用往往不在一个线程中,所以此处的阻塞不会影响真正的IO操作。当套接字可读,select返回,回调执行recvfrom,完成输入操作。如下图所示:
如果只是线性地看两个阶段是否有阻塞,IO复用似乎没什么优势。但实际上,使用select的优势在于“多路复用”,即一个selector等待多个文件描述符。
信号驱动式I/O模型,先通过sigaction调用安装一个信号处理函数,并立即返回。当套接字可读时,内核发送SIGIO信号通知应用程序,执行recvfrom方法执行IO输入。如下图所示:
这种模型,在接收到SIGIO信号之前,进程不会被阻塞。
前面四种IO模型,实际上在第二阶段(从内核缓冲区读取数据到用户缓冲区)都是阻塞的。而异步I/O模型在两个阶段都是非阻塞的。即先告知内核启动IO操作,立即返回,在两个阶段(准备数据和读取数据)全部完成时,内核发送信号通知用户进程。如下图所示:
首先明确两个概念:同步I/O和异步I/O,POSIX对其定义如下:
五种模型的对比如下
五种I/O模型中,除了异步I/O,其余四种或多或少都有阻塞的过程。因此,按照POSIX的标准,阻塞式I/O模型、非阻塞式I/O模型、I/O复用模型、信号驱动式I/O模型,都称之为同步I/O。
原文:https://www.cnblogs.com/buptleida/p/12944045.html