源地址http://blog.csdn.net/lonelyrains/article/details/6604851
linux文件IO操作有两套大类的操作方式:不带缓存的文件IO操作,带缓存的文件IO操作。不带缓存的属于直接调用系统调用(system call)的方式,高效完成文件输入输出。它以文件标识符(整型)作为文件唯一性的判断依据。这种操作不是ASCI标准的,与系统有关,移植有一定的问题。而带缓存的是在不带缓存的基础之上封装了一层,维护了一个输入输出缓冲区,使之能跨OS,成为ASCI标准。大体说来,不带缓存的方式频繁进行用户态和内核态的切换,高效但是需要程序员自己维护;带缓冲的方式因为有了缓冲区,不是非常高效,但是易于维护。由此,不带缓冲区的通常用于文件设备的操作,而带缓冲区的通常用于普通文件的操作。
之前看到有人把不带缓冲区的方式定义为低级IO操作,而带缓冲区的方式定义为高级IO操作。从是否是直接系统调用的角度,这个说法是成立的。但是,不带缓冲区的方式里,又有5种IO处理模型的划分,这5种二级范畴的IO处理模型的讨论全都是被称为高级IO操作的。为了不至于混淆,不把不带缓冲区的IO操作称为低级IO操作,而称为非ASCI标准的文件IO操作。
刚说了,不带缓冲区的方式高效但是需要程序员自己维护,包含5种对我个人来说比较难以理解的处理模型。现在就来谈谈这5中处理模型:阻塞IO模型、非阻塞模型、IO多路转接模型、信号驱动IO模型、异步IO模型。
很多人对阻塞和非阻塞、同步和异步的概念混淆不清。我举一个非常简单的例子,把大象关进冰箱需要三步:开门、把大象放进冰箱、关门。阻塞的意思是:开门开不了,一直猫在那等着;非阻塞的意思是:开门开不了,等下再来看看。同步的意思是:开不开门的请求和等待开不开门的结果是有序的;异步的意思是:假设要装两头大象进冰箱,如果冰箱门是开的,可以提交两条把大象放进冰箱的请求,而不是等待第一条请求有了结果之后再决定是否发出第二条请求。也就是说,阻塞非阻塞是针对具体应用的,而同步同步是仅指的通信应答方面。计算机科班的学生可能对前者理解更深刻,而通信科班的学生可能对后者理解的更深刻。不过,在讨论文件IO的时候,这个情况有些特殊。异步IO模型指的并不是异步通信的实质,而是不含阻塞的现象。
言归正传,来谈不含缓存的五种IO模型。
1、阻塞IO模型:从开门到把大象放进去到关门,一直是守着的,不干别的。所以,有多少步就有多少次阻塞。
2、非阻塞模型:当前是不是可以开门?不是。哦,干点别的。当前是不是可以开门?……如果不可以,一直重复上述步骤。直到——当前是不是可以开门?是。好的,开门。然后针对以下步骤重复上面的操作。但是实际文件IO操作,从内核把数据拷到用户进程的操作,仍然是阻塞的。
3、IO多路转接模型:在一个循环体中,实现对几套把大象关进冰箱的操作,而所用的冰箱是不同的冰箱,所以不存在冲突问题。在第一个冰箱关进冰箱需要等待的时候,就看第二个能不能执行。这种方式与用多线程下,每个子线程执行阻塞IO模型的操作类似。这个调度过程由OS执行。
4、信号驱动IO模型:发出打开冰箱的请求之后,可以干别的了。直到内核通知你可以等待从内核态拷贝数据了。从内核把数据 拷到用户进程的操作,仍然是阻塞的。
5、异步IO模型:发出打开冰箱的请求之后,可以干别的了。直到完成从内核到用户进程的数据拷贝,再通知用户。
参考 Unix Network Programming Volume 1。理解不透彻的地方,加强交流。