基础之IO的同步、异步、阻塞、非阻塞
重新梳理同步IO、异步IO、阻塞IO、非阻塞IO等相关概念。
在学习这些知识的时候,需要先限定一个范围,才能更好地解释。这里限定的范围是:Linux环境下的网络IO。
POSIX对同步IO和异步IO的定义如下:
- 同步IO操作导致请求进程阻塞,直到IO操作完成
- 异步IO操作不导致请求进程阻塞。
建议先阅读下《UNIX网络编程 卷一:套接字联网API(第三版)》第6.2节:I/O模型。
再缩小一下讨论的范围:Linux环境下的网络IO,并且是进程从网络获取数据这一操作。
进程从网络获取数据这一网络IO操作涉及到的对象有:
- 进程
- 系统内核
- 数据
进程从网络获取(read)数据会包含两个不同的阶段:
- 等待数据准备好
- 从内核向进程复制数据
等待数据准备好是指:等待数据从网络中到达,当数据分组到达时,数据会被复制到内核中的某个缓冲区中。
从内核向进程复制数据是指:把内核缓冲区中的数据复制到应用进程缓冲区。
同步IO、异步IO、阻塞IO、非阻塞IO这几个概念就是针对上面这两个阶段的不同情况来作区分的。
UNIX网络编程中将IO模型分成了五种:
- 阻塞IO模型
- 非阻塞IO模型
- IO复用模型
- 信号驱动式IO模型
- 异步IO模型
进程进行IO操作的一般包含:
- 进程发起recvfrom系统调用
- 系统内核等待数据准备好
- 系统内核将数据拷贝到进程缓冲区
- 系统内核通知进程结果
阻塞IO模型
从进程发起recvfrom系统调用,到系统内核等待数据准备好,再到系统内核将数据拷贝到进程缓冲区,最后到系统内核通知进程结果的过程中,进程都一直阻塞等待,直到系统内核告知了进程最后结果,进程才能解除阻塞,重新运行。
进程在IO执行的两个阶段:系统内核等待数据准备好、系统内核将数据拷贝到进程缓冲区,都被阻塞住了。
非阻塞IO模型
进程发起recvfrom系统调用后,如果没有数据准备好,系统内核会立刻返回一个错误给进程,进程会不断的进行recvfrom系统调用,直到系统内核准备好了数据。如果系统内核准备好了数据,进程发起的recvfrom系统调用就会阻塞住,等待系统内核将数据拷贝到进程缓冲区中,直到系统内核告知进程最后结果,进行才能解除阻塞,重新运行。
进程在IO执行的第一个阶段:系统内核等待数据准备好,没有被阻塞;在IO执行的第二个阶段:系统内核将数据拷贝到进程缓冲区,这一步被阻塞住了。
IO复用模型
IO复用模型实际应用是:select、poll、epoll。这种模型的核心思想就是一个进程可以同时处理多个网络连接。
进程发起select系统调用后,进程就会阻塞住,系统内核等待数据准备好后,select调用就会返回给进程结果,这时候进程会再发起一个recvfrom系统调用,此时数据准备好了,不需要阻塞在:系统内核等待数据准备好这一阶段,但是会阻塞在系统内核将数据拷贝到进程缓冲区中这一阶段,最后系统内核告知进程最后结果,进程才能解除阻塞,重新运行。
对于进程来说整个阶段还是阻塞的,只是阻塞在了select系统调用上。
信号驱动式IO模型
进程会首先发起一个sigaction系统调用,之后立刻返回,进程继续执行其他工作,进程没有被阻塞,也就是进程不需要阻塞在:系统内核等到数据准备好这一阶段。系统内核等到数据准备好之后,会返回给进程一个SIGIO信号,进程收到信号后发起recvfrom系统调用,此时数据准备好了,进程会阻塞在系统内核将数据拷贝到进程缓冲区中这一阶段,最后系统内核告知进程最后结果,进程才能解除阻塞,重新运行。
异步IO模型
进程会首先发起一个aio_read系统调用,并立即返回,进程继续其他工作,没有被阻塞。系统内核等到数据准备好,并将数据从内核拷贝到进程缓冲区中之后,会向进程发起一个信号,数据已经复制完成。
阻塞IO和非阻塞IO区别
阻塞IO和非阻塞IO的区别:从进程的角度看就是发起网络IO后,进程是阻塞等待还是立刻返回,如果是阻塞等待的就是阻塞IO,如果是立刻返回的就是非阻塞IO。
同步IO和异步IO区别
POSIX对同步IO和异步IO的定义如下:
- 同步IO操作导致请求进程阻塞,直到IO操作完成
- 异步IO操作不导致请求进程阻塞。
所以阻塞IO模型、非阻塞IO模型、IO复用模型、信号驱动式模型都有造成进程阻塞,都是同步IO。而异步IO模型没有导致请求进程阻塞,是异步IO。
最后还是要说一下,讨论阻塞和非阻塞、同步和异步,一定要划定一个范围,也就是要有上下文,才能尽可能正确的理解。
最后个人理解,在网络IO操作中:
- 阻塞和非阻塞是站在进程的角度来看,这一次网络IO是阻塞还是非阻塞的
- 同步和异步是站在我们的角度看进程是不是阻塞和非阻塞
参考
- 《UNIX网络编程 卷一:套接字联网API(第三版)》
- https://blog.csdn.net/historyasamirror/article/details/5778378