网络编程中,经常提到阻塞非阻塞/同步异步的概念,有时候容易让人混淆具体概念的意思。《UNIX网络编程》卷一中讲的蛮清楚的。引用整理下。
IO模型
IO复用: 内核一旦发现进程指定的一个或多个IO条件就绪(输入已准备好被读取,或者fd已能承接更多的输出),它就通知进程。这个能力称为IO复用(IO multiplexing)。
阻塞/非阻塞模型
这个是指IO模型,以recvfrom
系统调用为例。进程调用recvfrom
,其系统调用直到数据报到达且被复制到应用进程的缓冲区中或者发生错误才返回。我们就说进程在从调用recvfrom
开始到它返回的整段时间内是被阻塞(blocking)的。
进程把一个socket设置成非阻塞(nonblocking)是在通知内核:当所请求的IO操作非得把本进程投入睡眠才能完成时,不要把本进程投入睡眠,而是返回一个错误。
IO复用模型
可以调用select
或poll
,阻塞在这两个系统调用中的某一个之上,而不是阻塞在真正的IO系统调用上。这个是我们现在常用的模型。
信号驱动式IO模型
signal-driven IO,就是用信号,让内核在fd就绪时发送SIGIO
信号通知我们。在等待数据报到达期间进程不被阻塞,只要等待来自信号处理函数的通知。
异步IO模型
asynchronous IO,由内核通知我们IO操作何时完成。这个模型与上述四种模型不同,在等待IO完成期间,我们的进程不被阻塞。举例说,上述四个模型在执行recvfrom
时都是阻塞进程的;而这个模型在等待IO完成期间,进程不被阻塞。
目前支持这个模型的貌似只有WINDOWS的IOCP(?)。
对比
同步IO操作导致请求进程阻塞,直到IO操作完成。
异步IO操作不知道请求进程阻塞。