首页 > 代码库 > 第3章 文件I/O(5)_五种I/O模型
第3章 文件I/O(5)_五种I/O模型
6. I/O处理方式(5种I/O模型)
(1)阻塞I/O模型:若所调用的I/O函数没有完成相关的功能就会使进程挂起,直到相关数据到达才会返回。如:终端、网络设备的访问。整个过程分为两个阶段:
①阶段一是等待数据就绪,网络I/O的情况就是等待远端数据陆续抵达;磁盘I/O的情况就是等待磁盘数据从磁盘上读取到内核态内存中。
②阶段二是数据拷贝,出于系统安全,用户态的程序没有权限直接读取内核态内存,因此内核负责把内核态内存中的数据拷贝一份到用户态内存中。理解这两个阶段非常重要,后续I/O模型的演变都是针对这两个阶段进行不同改造。
(2)非阻塞模型:当请求的I/O操作不能完成时,则不让进程休眠,而且返回一个错误。如open、read和write访问。
①阶段一频繁轮询的话,也很耗费CPU时间这种方式对单个I/O请求意义不大,但给I/O多路复用铺平了道路。 低速系统调用时,进程可能会阻塞。
②非阻塞I/O操作(open、read、write)不阻塞,如果操作不能完成,则出错返回
③设定非阻塞的方式:使用open打开文件,设置O_NONBLOCK标志。如果一个文件己经打开,则使用fcntl修改文件状态标志。
(3)I/O多路转接模型:如果请求的I/O操作阻塞,且他不是直正阻塞I/O,而且让其中的一个函数等待,在这期间,I/O还能进行其他操作。如:select函数。
①调用 select/poll该方法由一个用户态线程负责轮询多个sockets,直到某个阶段一的数据就绪,再通知实际的用户线程执行阶段二的拷贝。
②通过一个专职的用户态线程执行非阻塞I/O轮询,模拟实现了阶段一的异步化。
(4)信号驱动I/O模型:在这种模型下,通过安装一个信号处理程序,系统可以自动捕获特定信号的到来,从而启动I/O。(类似于观察者模式)。阶段一演变为异步,由内核托管,应用程序只需告知内核,当阶段一数据就绪时向应用程序发出 SIGIO信号。至此为止,前述4种模型的阶段二仍是处于block状态的。
(5)异步I/O模型:在这种模型下,当一个描述符己准备好,可以启动I/O时,进程会通知内核。由内核进行后续处理。当整个过程(包括阶段一和阶段二)全部完成时,通知应用程序来读数据。这种用法现在较少。
【附】5种模型的比较
【编程实验】非阻塞I/O的read调用。
#include <unistd.h> #include <fcntl.h> #include <stdio.h> #include <stdlib.h> #include "io.h" int main(void) { char buffer[4096] = {0}; ssize_t size = 0; //默认,IO是阻塞的,后面的read会阻塞等待键盘输入。 //以下演示非阻塞IO的读取。 set_fl(STDIN_FILENO, O_NONBLOCK); sleep(5); size = read(STDIN_FILENO, buffer, sizeof(buffer)); if(size < 0 ){ perror("read error"); exit(1); }else if (size == 0){ printf("read finished\n");//进程执行过程中,在没有键盘输入并按ctrl+D //会执行到这里。 }else{ if(write(STDOUT_FILENO, buffer, size) != size){ perror("write error"); exit(1); } } return 0; }
第3章 文件I/O(5)_五种I/O模型