阻塞I/O:套接字在调用接口时,会一直处于等待状态,直到内核将数据准备好返给套接字,如下图:

  同步异步阻塞非阻塞_第1张图片

非阻塞I/O:套接字在调用接口时,每请求一次数据,内核根据是否准备好数据都会返回给套接字信息,如果内核没准备好,返回一个错误状态码,准备好返回数据,这样会消耗大量的cpu,如下图:


同步异步阻塞非阻塞_第2张图片

I/O复用:I/O复用方式主要包含select、poll、epoll,他们作为代理来处理I/O请求,I/O复用是阻塞和非阻塞的综合,可以处理多个请求,所有的请求都要经过代理,代理判断内核是否准备好数据,内核准备好数据后会通知代理,(select和poll在接受到内核的通知后会将所有请求轮询,确定是哪一个请求的数据准备好了,然后返回给数据,没有准备好数据的请求,依然阻塞在select和poll内;epoll是升级版的代理,内核准备好数据后,通知epoll,epoll只是轮询准备好的数据,直接将数据发送给响应的请求,其他没准备好的请求依然阻塞)如下图:


异步I/O:这类函数的工作机制是告知内核启动某个操作,并让内核在整个操作(包括将数据从内核拷贝到用户空间)完成后通知我们,如下图:



对unix来讲:阻塞式I/O(默认),非阻塞式I/O(nonblock),I/O复用(select/poll/epoll)都属于同步I/O,因为它们在数据由内核空间复制回进程缓冲区时都是阻塞的(不能干别的事)。只有异步I/O模型(AIO)是符合异步I/O操作的含义的,即在1数据准备完成、2由内核空间拷贝回缓冲区后 通知进程,在等待通知的这段时间里可以干别的事


例如:

  1. 我去买一本书,立即买到了,或者没有就走了,这就是非阻塞;(编程中设置IO成非阻塞,返回后再去检查描述符,或者等待通知,然后再去读取。相当于老板告诉我可以先忙点别的,过一会再来问问,或者老板通知我。但期间这个窗口(文件描述符)别人是用不了的)("立即买到了"在IO中也需要等待,不能算非阻塞IO)

  2. 如果恰好书店没有,我就等一直等到书店有了这本书买到了才走,这就是阻塞;而排在我后面的人呢只有我买到了书后才能再买书了。

  3. 如果书店恰好没有,我就告诉书店老板,书来了告诉我一声让我来取或者直接送到我家,然后我就走了,去做别的事了,这就是异步。这时候如果很多人来买书,都是老板登记一下完事。 (从IO角度来说,“告诉我来取”,这个近似于信号驱动IO,不能算异步IO。必须书送到我家才算是异步,如果不送到我家,我想看这本书之前,终究还是需要我跑一趟)

  4. 前面两种情况,非阻塞和阻塞都可以称为同步。

反映在编程方面就是 用户进程 调用 系统调用。(用户进程对应我,内核 对应 书店老板,书对应数据资源data , 买书就是一个系统调用了,其中内核拷贝数据到进程这个过程近似于老板送书到我手中)。



作者:Shihui wang
链接:https://www.zhihu.com/question/19732473/answer/14413599
来源:知乎
著作权归作者所有,转载请联系作者获得授权。