jason--liu/Blog

5种IO模型、阻塞/非阻塞IO、同步/异步IO

jason--liu opened this issue · 0 comments

linux下的IO模型一直没有理解清楚过,直到最近的学习实战才有了较深入的理解。
5种IO模型分别是阻塞IO模型、非阻塞IO模型、IO复用模型、信号驱动的IO模型、异步IO模型;前4种可以称为同步IO操作,只有异步IO模型是异步IO操作。

阻塞IO

先看一个图。
image
阻塞和非阻塞主要是指调用某个系统函数时,这个函数是否会导致我们的进程进入休眠状态而言的。调用一个函数,这个函数就卡在在这里,整个程序流程不往下走了,该函数卡在这里等待一个事情发生,只有这个事情发生了,这个函数才会往下走,这种函数,就认为是阻塞函数。比如前面说的accept()函数。

非阻塞IO

不会阻塞当前进程,充分利用时间片,执行效率更高。看一下它的应用模型。
image
可以看到非阻塞IO一般需要轮询,不断检查是否有数据到来,比较“累”。如果没有数据到来,函数会返回一个特殊标记回来,比如EWULDBLOCK,也可能是EAGAIN。如果有数据到来那么也得卡在这里等待数据从内核数据缓冲区拷贝到用户缓冲区,所以这个复制阶段还是阻塞的。

同步与异步IO

异步IO模型
image
异步I/O:调用一个异步I/O函数时,我们要给这个函数指定一个接收缓冲区,还要给定一个回调函数;调用完一个异步I/O函数后,该函数会立即返回。 其余判断交给操作系统,操作系统会判断数据是否到来,如果数据到来了,操作系统会把数据拷贝到我们所提供的缓冲区里,然后调用指定的回调函数来通知我们。同步IO就是导致请求进程阻塞,直到I/O操作完成。

IO复用

image
所谓I/O复用,就是我多个socket(多个TCP连接)可以弄成一捆,用select这种同步I/O函数在这等数据;select()的能力是等多条TCP连接上的任意一条有数据来,然后哪条TCP有数据来,我们再用具体的比如recvfrom()去收。所以,这种调用一个函数能够判断一堆TCP连接是否来数据的这种能力,叫I/O复用,英文I/O multiplexing。

几种IO模型比较

image
可以看到,只有异步IO才是真正没有阻塞行为发生的。