美文网首页
同步IO/异步IO, 阻塞IO/非阻塞IO

同步IO/异步IO, 阻塞IO/非阻塞IO

作者: 听海吹牛逼的声音 | 来源:发表于2018-09-27 15:29 被阅读0次

    前提知识:用户态与内核态

    开篇,我觉得应该先给这四个画一个等级。
    同步IO和异步IO是更高层次的一个划分,阻塞IO/非阻塞IO同属于同步IO类别下,但是是不同的小类别。

    1.同步IO(synchronous IO)
    我以前有个误解:同步IO就代表着用户进程会在IO时等待,这个理解对了一半错了一半。看完下面就能豁然开朗了。
    同步IO分为以下4种
    1.1 阻塞IO (blocking IO)
    用户进程在要访问网卡的时候,由于用户态没有这个权限,是需要调用系统函数recvfrom从用户态切换到内核态,
    由于内核也需要从网卡上读取数据,所以在数据还没有准备好的时候,用户的进程就被阻塞这。内核读完了网卡数据,然后需要从内核空间再拷贝到用户内存空间。此时用户进程算是得到了数据,不再被阻塞,从而继续运行。
    1.2 非阻塞IO (nonblocking IO)
    用户调用recvfrom想要读数据,并设置参数flag为非阻塞的。此时发现内核态并没有准备好数据呢,好,那内核就告诉进程,数据还没有搞定,立即返回,那用户进程发现没有数据呢,那就先去干别的事情;过一会用户进程又来问内核要数据,此时内核已经准备好数据了,那内核负责将内核空间的数据拷贝到用户空间,然后函数返回,此时回到用户态。注意,这里其实依然是有个同步(或者叫短暂的阻塞),就是进程需要等待内核把数据从内核空间拷贝到用户空间。
    1.3 多路复用IO (IO multiplexing)
    select/poll/epoll 听过吧,其实就是用一个文件句柄来handle很多个socket,如果这个socket已经准备好数据了,那就用调用recvfrom来取数据。这个层次能相当于一个封装。 调用select/poll的时候,会去轮询所有在监听的file descriptor(文件描述符),如果说这个fd对应的数据ok了,放进fd_set里,最后返回这些fd,把他们从内核空间拷贝到用户空间,然后用户进程就拿到了这些fd,针对每个fd,用户进程需要调用recvfrom去把网络数据从内核空间拷贝到用户空间来。这里和阻塞IO/非阻塞IO有点不同,因为这些fd是已经确定数据ready了,所以比阻塞IO阻塞时间短,又不会像非阻塞IO那样可能数据没有准备好。epoll更高效一些,下一篇文章再详解epoll。特别注意,这里仍然是同步的概念,因为仍然需要把网络数据从内核里考到用户态里。
    1.4 信号驱动IO (signal driven IO)
    了解点宏观原理,再细节点不懂。原理就是用sigaction注册fd的处理函数,一旦这个fd数据ready了,通知对应的处理进程,这个进程再把数据从内核里拷贝出来。同上,有这个拷贝的过程,所以依然数据同步IO。

    2.异步IO (asynchronous IO)
    ok,终于到异步IO了。用户进程调用aio_read,告诉内核等数据准备好,并且复制到用户进程空间后执行事先指定好的函数,并且这个read会立即返回。当数据已经完成并复制到了用户空间,就会产生一个信号或执行一个基于线程的回调函数来完成这次 I/O 处理过程。

    3.总结一下
    异步和同步的差异:其实关键点就在与用户进程是否在等待把数据从内核空间拷贝到用户空间。所以阻塞不阻塞和同步没有啥关系。只要用户进程需要等待拷贝,那就是同步。
    阻塞和非阻塞差异:阻塞和非阻塞都有短时间的等待拷贝过程,但是非阻塞IO会在没有数据的情况下不傻等。

    4.更形象的例子
    举个栗子,好理解又好记忆。
    你是个人,对,叫A,你需要接电话,电话里的人B会告诉你一个串数字,你要给记下来,之后有用。
    你就是用户进程,电话就是函数,电话里的人是内核进程。
    (1.1)阻塞IO:你打电话给对方,要数字,因为B也没有那个数字呢,所以你就举着电话不放下,拼命等,等了半个小时后,B有数字了,告诉你,你给数字写到纸条上,挂电话。好的拿数字任务完成。
    (1.2)非阻塞IO:你9点打电话给B,要数字,B说没有,好你挂了电话,去打球了。10点你又打,还没有,你又出去了。11点你再打电话,诶B告诉你有了,于是你记下来,挂电话。任务搞定。
    (1.3)多路复用IO:你找了个新工作,现在变成了接线员,这有10个电话,每个电话你每隔一小时都打一下,问问对面有没有新的数字呢,对面如果说有,你把这个电话编号记下来。都打完了,把这些有新的数字的电话编号给你的客户们,然后告诉他们,你们可以打电话去要数字了,然后你的那些拿到号码的客户,去对应的电话打电话要数字,他们再把自己要的数字写在小纸条上。
    (1.4)信号驱动IO: 你又不再是接线员了,做回个需要数字的人。你打电话告诉B,你那边数字搞定了打电话给我。然后出去喝酒了。B那边数据准备好了,打电话给你,你接电话,并把数字记录到小纸条上,然后挂电话。任务搞定。
    (2)异步IO: 你变成老板了,牛逼炸了,打电话告诉B,你那边一旦拿到数字,你把数字写下来,把那个纸条给我亲自送过来,所以我就不用自己花时间来写纸条了,将来就直接用就可以了。

    一些参考的博客:
    信号驱动IO
    https://blog.csdn.net/historyasamirror/article/details/5778378
    https://www.cnblogs.com/langzibin/p/7755783.html

    相关文章

      网友评论

          本文标题:同步IO/异步IO, 阻塞IO/非阻塞IO

          本文链接:https://www.haomeiwen.com/subject/zpidoftx.html