IO模型 - Unix IO模型
一个输入操作通常分为两步:
- 等待数据准备好
- 从内核向进程复制数据
前言
对于一个套接字的输入操作,第一步通常等待数据从网络中到达,当所等分组到达时,复制到内核某个缓冲区,第二部就是再从内核缓冲区复制到应用进程缓冲区。
一、阻塞式IO
应用进程阻塞,直到复制到应用进程缓冲区后返回。
在阻塞的过程中,其它程序还可以执行,因此阻塞不意味着整个操作系统都被阻塞。
因为其他程序还可以执行,因此不消耗 CPU 时间,这种模型的执行效率会比较高。
二、非阻塞式IO
应用程序执行系统调用后,内核返回一个错误码。应用程序可继续执行,但要不断的执行系统调用来获取IO是否完成,这个过程称为轮询。
但CPU要处理更多的系统调用,因此这种模型是比较低效的。
三、IO复用
使用select或poll等待数据,并且可以等待多个套接字中的任意一个变为可读,这一过程会被阻塞,当某一个套接字可读时返回。之后将数据从内核缓冲区复制到应用进程缓存区。
它可以让单个进程具有处理多个 I/O 事件的能力。又被称为 Event Driven I/O,即事件驱动 I/O。
如果一个web项目没有使用IO复用,那么每有一个socket连接,就要新建一个线程,如果有成千上万个连接,那就需要建立相应数量的线程。
相比于多进程和多线程技术,IO复用不需要进程线程创建和切换的开销,因此系统开销更小
四、信号驱动式IO
应用进程使用 sigaction 系统调用,内核立即返回,应用进程可以继续执行,也就是说等待数据阶段应用进程是非阻塞的。
内核在数据到达时向应用进程发送 SIGIO 信号,应用进程收到之后在信号处理程序中调用 recvfrom 将数据从内核复制到应用进程中。
相比于非阻塞式 I/O 的轮询方式,信号驱动 I/O 的 CPU 利用率更高。
五、异步IO
进行 aio_read 系统调用会立即返回,应用进程继续执行,不会被阻塞,内核会在所有操作完成之后向应用进程发送信号。
异步 I/O 与信号驱动 I/O 的区别在于,异步 I/O 的信号是通知应用进程 I/O 完成,而信号驱动 I/O 的信号是通知应用进程可以开始 I/O。