对同步和异步、阻塞和非阻塞这些名词困惑了很久了,曾经相当然的认为阻塞就是同步、非阻塞就是异步,这也是典型的错误,后来从Unix网络编程卷1上才看到最全面的解析,下面主要的内容来自Unix网络编程,算是自己的一个学习笔记吧!
由于这本书中面向的是Unix编程,所以在其他的环境中IO模型可能会有稍微的不同,比如Java中的IO模型,但是也不会相差很多,毕竟Unix作为众多技术的鼻祖,很多的思想和实现都来自它。
首先要明白输入和输出操作的过程,这个过程包括两个阶段:
- 等待数据准备好:这里所说的准备好指的是数据已经到硬件设备上了,而不管该数据的来源是什么,可能是通过网线或者无线电传输过来的010101,还有可能是本机进程通过系统调用写到存储器上的101011,总而言之此时硬件设备上必须要有对应的数据才能算是准备好;
- 将数据从内核中复制到相应的进程中:更明确的说,是通过内核将硬件设备上的数据复制到进程空间中然后进行进一步的操作,这个过程其实是应用进程通过调用内核提供的系统接口完成的。
这个过程如下图:
其实在这个过程中内核空间其实是担当了一个代理人的角色,进程通过调用内核提供的系统接口才能读取硬件上存储的数据。所以上面的两个过程说的更抽象一点:一个是硬件已经存在数据,软件能够读取数据。
由于上图也涉及到了进程之间的通信,有必要说明一下,进程之间通信不一定要通过操作系统内核,比如共享内存就不会经过内核,但是其他的比如管道等还是会经过内核。
一、阻塞式I/O模型
对于写过IO程序的人来说,这种模型一定不陌生,不管是使用C还是Java,内部默认的都是这种IO模型,这类所谓的阻塞其实是指应用进程受阻于内核提供的系统调用,