「Linux」- 五类 I/O 模型(学习笔记)

在 UNIX Network Programming 中,给出五类 I/O 模型:

1)blocking IO ———– 阻塞 IO

2)nonblocking IO ——– 非阻塞 IO

3)IO multiplexing ——- IO 多路复用

4)signal driven IO —— 信号驱动 IO

5)asynchronous IO ——- 异步 IO

前面四种 IO 都可以归类为 Synchronous IO(同步IO)。

阻塞(BLOCKING I/O)

最容易理解的是阻塞。在一次网络 I/O 时,Client 发出请求,Server 收到。当 Client 发出请求,进行 I/O 时,就不能进行其他操作,需要同步的等待结果的返回。

用户进程 Process 在 Blocking IO 读 recvfrom 操作的两个阶段都是等待的。在数据没准备好的时候,Process 原地等待 kernel 准备数据。kernel 准备好数据后,Process 继续等待kernel 将数据复制到自己的 buffer。在 Kernel 完成数据复制后,Process 才会从 recvfrom 系统调用中返回,然后继续执行其他操作。

非阻塞(NONBLOCKING I/O)

process 在 NonBlocking IO 读 recvfrom 操作的第一个阶段是不会 block 等待的,如果 kernel 数据还没准备好,那么 recvfrom 会立刻返回 EWOULDBLOCK 错误。当 kernel 准备好数据后,进入处理的第二阶段的时候,process会等待 kernel 将数据 copy 到自己的 buffer,在 kernel 完成数据的 copy 后 process 才会从 recvfrom 系统调用中返回。

I/O 多路复用(I/O MULTIPLEXING)

当使用 I/O 多路复用时,有多个 Client 同时发送请求,这些 I/O 操作会被 selector(epoll,kqueue) 给暂时挂起,放入内存队列。此时 Server 可以自己选择什么时候读取、处理这些 I/O,也就是说 Server 可以同时持有多个 I/O。

但是 I/O 多路复用,在没有用特殊异步 API 的情况下,还是同步的操作。

在 IO 多路复用的时候,process 在两个处理阶段都是 block 住等待的。初看好像 IO 多路复用没什么用,其实 select、poll、epoll 的优势在于可以以较少的代价来同时监听处理多个IO。

事件驱动(SIGNAL DRIVEN I/O)

异步(POSIX AIO)

异步 IO 要求 process 在 recvfrom 操作的两个处理阶段上都不能等待,也就是 process 调用 recvfrom 后立刻返回,kernel 自行去准备好数据并将数据从 kernel 的 buffer 中 copy 到 process 的 buffer,再通知 process 读操作完成了,然后 process 在去处理。

遗憾的是,linux的网络IO中是不存在异步IO的,linux的网络IO处理的第二阶段总是阻塞等待数据copy完成的。真正意义上的网络异步IO是Windows下的IOCP(IO完成端口)模型。

相关链接

Networking and IO Models | Seena Burns

参考文献

io多路复用 – 简书
Select、Poll和Epoll_ajuse的博客-CSDN博客_poll epoll