阻塞、非阻塞、异步、同步

来源:milter

POSIX(可移植操作系统接口)把同步IO操作定义为导致进程阻塞直到IO完成的操作,反之则是异步IO

这些概念之所以容易令人迷惑,在于很多人对I/O就没有清晰准确的理解,后面的理解自然不可能正确。我想用一个具体的例子来说明一下I/O。
设想自己是一个进程。这个进程需要接收一个输入,我们不管这个输入是从网络套接字来,还是键盘,鼠标来,输入的来源可以千千万万。但是,都必须由内核来帮进程完成,为啥内核这么霸道?因为计算机上运行的可不只是咱进程一个进程,还有很多进程。这些进程兄弟也可能需要从这些输入设备接收输入,没有内核居中协调,岂不是乱套。
从进程的角度看,内核帮助它完成输入,其实包括三个步骤:

  • 1、内核替进程接收好数据,这些数据暂时存在内核的内存空间
  • 2、内核将数据从自己的内存空间复制到进程的内存空间
  • 3、告诉(通知)进程,输入数据来了,赶快读吧

这三步看似挺简单,其实在具体实现时,有很多地方需要考虑:

  • 0、进程如何告诉内核自己要接收一个输入?
  • 1、内核接到进程的请求,替进程接收好数据这段时间, 进程咋办?
  • 2、内核在将数据复制到进程的内存空间这段时间,进程咋办?
  • 3、到底什么时候告诉进程数据准备好了,是在内核接收好数据之后就告诉进程,还是在将数据复制到进程的内存空间之后再告诉他?
  • 4、内核以什么样的方式告诉进程,数据准备好了?

2、阻塞式I/O模型

对上面5个问题,最简单的解决方案就是阻塞式I/O模型,它的过程是这样的:
进程:内核内核,我要接收一个键盘输入,快点帮我完成!
内核:好咧!biubiu!内核迅速将进程阻塞,可怜的进程顿时石化,就像被孙悟空点了定一样。
就这样,进程在石化中,时间一点点流逝。终于,内核收到了数据。
内核:数据终于来了,我要开干了!duang duang duang,先把数据存在自己的内核空间,然后又复制到进程的用户空间。
内核:biubiu!内核解除了进程的阻塞,进程瞬间复活,进程的记忆还是停留在让内核帮他接收输入时。
进程:哇!内核真靠谱,数据已经有了!干活去!

我们可以看到,进程发出接收输入的请求给内核开始,就处于阻塞状态,直到内核将数据复制到进程的用户空间,进程才解除阻塞。
以上过程可通过下图来解释:

同步阻塞IO

3、非阻塞式I/O

进程发现,阻塞式I/O中,自己总要被阻塞好久,好不爽啊,于是进程改用了非阻塞式I/O,其过程是这样的:
进程:内核内核,我要接收一个输入,赶紧帮我看看,数据到了没有,先说好,不要阻塞我。
内核:查看了一下自己的内核空间,没有发现数据,于是迅速告诉进程,没有呢!并继续帮进程等着数据。
如此这样,进程不断地问内核,终于,过了一段时间,进程再一次询问时,内核往自己的空间中一查,呦!数据来了,不胜其烦的内核迅速告诉进程,数据好了!
进程:快给我!
内核:biu!内核干净利落地阻塞了进程,悲催的进程还是石化了!
内核赶紧将自己空间的输入数据复制到进程的用户空间,复制好后。
内核:biu!内核解除了进程的阻塞,进程立马复活
进程:哇!数据来了,啥也不说,干活!

我们看到,所谓的非阻塞I/O,其实在内核将数据从内核空间复制到进程的用户空间时,进程还是被阻塞的。
具体过程如下图所示:

非阻塞IO

4、异步I/O

上面的两种I/O解决方案中,进程都被阻塞了,只不过是阻塞时间长短不一样。

  • 第一种方案中进程被阻塞的时间长一些,在内核接收数据以及将数据复制到进程的用户空间时,都被阻塞。
  • 第二种方案中,只在内核将数据从内核空间复制到进程的用户空间时,进程才被阻塞。

我们现在说的异步I/O,目的就是让进程绝对不被阻塞。其过程是这样的:
进程:内核内核,我要接收一个输入,弄好了告诉我。同时将一个信号和信号处理函数告诉内核,然后继续干自己的活了。
内核:得了您嘞,您先忙。
一直到内核接收到数据并将数据从内核空间复制到进程的用户空间后,内核才给进程发送信号。进程在信号处理函数中可以直接处理数据。
其过程可用下图解释:


异步IO

5、IO多路复用

在上面的阻塞IO中,我们的进程都是直接阻塞在IO系统调用recvfrom上,可以说是与IO系统调用“零距离”。

这种做法有一定的弊端,就是当进程要同时等待多个输入,哪个先来就处理哪个时,进程不知道哪个先来,自然也就不知道应该被阻塞到哪一个输入的recvfrom上好。

聪明如你,可能会说,那全部用异步IO呗。但这样也不方便,就是进程要为每一个输入都在系统中注册一个信号和信号处理函数,这可是要与内核打交道的。如果要等的输入非常多,岂不是非常的麻烦。

为了方便处理这种情况,进程可以使用一个输入管家,就是select系统调用,该调用可以帮助进程管理所有的输入(通常是套接字),每当一个输入中有数据到来时,就告诉进程。这样进程实际上是阻塞在select系统调用上,而不是阻塞在真正的IO系统调用上,如下图所示:


IO多路复用

6、那啥是同步呢?

一句话,凡是让进程阻塞(不管长短)的I/O方案都是同步I/O。也就是说,阻塞、非阻塞、信号驱动式都是同步I/O。

7、总结

IO分两阶段:

1.数据准备阶段
2.内核空间复制回用户进程缓冲区阶段

一般来讲:阻塞IO模型、非阻塞IO模型、IO复用模型(select/poll/epoll)、信号驱动IO模型都属于同步IO,因为阶段2是阻塞的(尽管时间很短)。只有异步IO模型是符合POSIX异步IO操作含义的,不管在阶段1还是阶段2都可以干别的事。

更多I/O模型

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 205,132评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,802评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,566评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,858评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,867评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,695评论 1 282
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,064评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,705评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 42,915评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,677评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,796评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,432评论 4 322
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,041评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,992评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,223评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,185评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,535评论 2 343

推荐阅读更多精彩内容