带下划线的部分是我的理解和译注
有五种I/O模型。
下图针对网络I/O,但磁盘I/O等其它I/O形式都是类似。
1,阻塞I/O模型
请求无法立即完成则保持阻塞。
整个过程分为两个阶段:
阶段一是等待数据就绪,网络I/O的情况就是等待远端数据陆续抵达;磁盘I/O的情况就是等待磁盘数据从磁盘上读取到内核态内存中。
阶段二是数据拷贝,出于系统安全,用户态的程序没有权限直接读取内核态内存,因此内核负责把内核态内存中的数据拷贝一份到用户态内存中。
理解这两个阶段非常重要,后续I/O模型的演变都是针对这两个阶段进行不同改造。
2,非阻塞I/O模型
请求不会阻塞, 而是立即返回错误码(EWOULDBLOCK)
(通过调用fcntl,参数置为O_NONBLOCK)
阶段一频繁轮询的话,也很耗费CPU时间
这种方式对单个I/O请求意义不大,但给I/O多路复用铺平了道路.
3,I/O多路复用模型
调用 select / poll 该方法由一个用户态线程负责轮询多个sockets,直到某个阶段一的数据就绪,再通知实际的用户线程执行阶段二的拷贝.
通过一个专职的用户态线程执行非阻塞I/O轮询,模拟实现了阶段一的异步化
4,信号驱动I/O模型
阶段一演变为异步,由内核托管,应用程序只需告知内核,当阶段一数据就绪时向应用程序发出 SIGIO信号
至此为止,前述4种模型的阶段二仍是处于block状态的
5,异步I/O模型
告知内核,当整个过程(包括阶段一和阶段二)全部完成时,通知应用程序来读数据.
linux3.5已经有针对C的异步I/O API,细节略.