五种 I/O 模型简述

相关概念

同步和异步

描述的是用户线程与内核的交互方式:

  • 同步是指用户线程发起 I/O 请求后需要等待(阻塞)或者轮询内核 I/O 操作(非阻塞)完成后才能继续执行;
  • 异步是指用户线程发起 I/O 请求后仍继续执行,当内核 I/O 操作完成后会通知用户线程,或者调用用户线程注册的回调函数

同步与异步一般是面向操作系统和应用程序对 IO 操作的层面上来区别的

同步时:应用程序会直接参与 IO 读写操作,并且应用程序会直接阻塞到某一个方法上,直到数据准备就绪;或者采用轮询的策略实时检查数据的就绪状态,如果就绪则获取数据

异步时:所有的 IO 读写操作交给操作系统处理,与应用程序没有直接关系,程序不需要关心 IO 读写,当操作系统完成 IO 读写操作时,会给应用程序发送通知,应用程序直接拿走数据即可

同步 / 异步描述的是执行 IO 操作的主体是谁,同步是由用户进程自己去执行最终的 IO 操作。异步是用户进程自己不关系实际 IO 操作的过程,只需要由内核在 IO 完成后通知它既可,由内核进程来执行最终的 IO 操作

阻塞和非阻塞

描述的是用户线程调用内核 I/O 操作的方式:

  • 阻塞是指 I/O 操作需要彻底完成后才返回到用户空间;
  • 非阻塞是指 I/O 操作被调用后立即返回给用户一个状态值,无需等到 I/O 操作彻底完成

阻塞 / 非阻塞描述的是函数,指访问某个函数时是否会阻塞线程

I/O 的两个阶段

阶段 1:等待数据就绪(发起 IO 请求)。网络 I/O 的情况就是等待远端数据陆续抵达;磁盘 I/O 的情况就是等待磁盘数据从磁盘上读取到内核态内存中

阶段 2:数据拷贝(实际 IO 操作)。出于系统安全,用户态的程序没有权限直接读取内核态内存,因此内核负责把内核态内存中的数据拷贝一份到用户态内存中

同步 IO 和异步 IO 的区别就在于第二个步骤是否阻塞,如果实际的 IO 读写阻塞请求进程,那么就是同步 IO,因此阻塞 IO、非阻塞 IO、IO 复用、信号驱动 IO 都是同步 IO,如果不阻塞,而是操作系统帮你做完 IO 操作再将结果返回给你,那么就是异步 IO

阻塞 IO 和非阻塞 IO 的区别在于第一步,发起 IO 请求后是否会被阻塞,如果阻塞直到完成那么就是传统的阻塞 IO,如果不阻塞,那么就是非阻塞 IO

同步与阻塞区别:

  • 同步和异步关注的是消息通信机制。同步在发出调用后,没得到结果之前不返回,但是一旦返回,就是调用结果;异步是调用发出后立即返回,但是没有返回结果,直到被调用者通过状态、通知、回调函数来通知调用者

  • 阻塞和非阻塞关注的是程序在等待调用结果时的状态。阻塞是指结果返回之前,当前线程会被挂起;非阻塞是指不能立即得到结果时,线程不会被阻塞

IO 就绪和完成的区别:就绪指的是还需要用户自己去处理,完成指的是内核帮助完成了,用户不用关心 IO 过程,只需要提供回调函数

select / poll / epoll 从本质上说都是同步非阻塞 IO,select 会收到 IO 就绪的状态,然后通知用户去处理 IO,实际的 IO 操作还需要用户等待内核复制操作

同步非阻塞 IO 指的是用户调用读写方法是不阻塞的,立刻返回的,而且需要用户线程来检查 IO 状态。需要注意的是,如果发现有可以操作的 IO,那么实际用户进程还是会阻塞等待内核复制数据到用户进程,它与同步阻塞 IO 的区别是后者全程等待

异步非阻塞 IO 指的是用户调用读写方法是不阻塞的,立刻返回,而且用户不需要关注读写,只需要提供回调操作,内核线程在完成读写后回调用户提供的 callback

五种 I/O 模型简述

  1. 阻塞 I/O 模型(同步阻塞)
    老李去火车站买票,排队三天买到一张退票
    耗费:在车站吃喝拉撒睡 3 天,其他事一件没干
Blocking IO
  1. 非阻塞 I/O 模型(同步非阻塞)
    老李去火车站买票,隔 12 小时去火车站问有没有退票,三天后买到一张票
    耗费:往返车站 6 次,路上 6 小时,其他时间做了好多事
Nonblocking IO

socket 设置为 NONBLOCK(非阻塞)就是告诉内核,当所请求的 I/O 操作无法完成时,不要将进程睡眠,而是返回一个错误码(EWOULDBLOCK),这样请求就不会阻塞

I/O 操作函数将不断的测试数据是否已经准备好,如果没有准备好,继续测试,直到数据准备好为止。整个 I/O 请求的过程中,虽然用户线程每次发起 I/O 请求后可以立即返回,但是为了等到数据,仍需要不断地轮询、重复请求,消耗了大量的 CPU 的资源

数据准备好了,从内核拷贝到用户空间

一般很少直接使用这种模型,而是在其他 I/O 模型中使用非阻塞 I/O 这一特性。这种方式对单个 I/O 请求意义不大,但给 I/O 多路复用铺平了道路

  1. I/O 复用模型(同步阻塞)
    老李去火车站买票,委托黄牛,等着黄牛拿票。黄牛买到后即通知老李去领,然后老李去火车站交钱领票
    select
    黄牛不断去轮询各个渠道问有没有票,轮询渠道数有限制,1024 个
    poll
    同样去轮询各个渠道,但是渠道数没限制
    epoll
    黄牛不轮询了,而是渠道有票数变化时才动身
    耗费:往返车站 1 次,路上 1 小时,黄牛手续费 100 元,看起来比阻塞 I/O 更贵,但是 1 个黄牛可以同时处理好几个客户的票啊
IO Multiplexing

I/O 多路复用会用到 select、poll 或者 epoll 函数,这两个函数也会使进程阻塞,但是和阻塞 I/O 所不同的是,这三个函数可以同时阻塞多个 I/O 操作。而且可以同时对多个读操作,多个写操作的 I/O 函数进行检测,直到有数据可读或可写时,才真正调用 I/O 操作函数

I/O 多路复用模型使用了 Reactor 设计模式实现了这一机制

select/poll 方法由一个用户态线程负责轮询多个 socket,直到某个阶段 1 的数据就绪,再通知实际的用户线程执行阶段 2 的拷贝。通过一个专职的用户态线程执行非阻塞 I/O 轮询,模拟实现了阶段一的异步化。而 epoll 函数不轮询,而是采用回调函数机制

从流程上来看,使用 select 函数进行 IO 请求和同步阻塞模型没有太大的区别(只不过是被 select 阻塞,而不是被 recvfrom 阻塞),甚至还多了添加监视 socket,以及调用 select 函数的额外操作,效率更差。但是,使用 select 以后最大的优势是用户可以在一个线程内同时处理多个 socket 的 IO 请求。用户可以注册多个 socket,然后不断地调用 select 读取被激活的 socket,即可达到在同一个线程内同时处理多个 IO 请求的目的。而在同步阻塞模型中,必须通过多线程的方式才能达到这个目的

如果处理的连接数不是很高的话,使用 select/epoll 不一定比使用 multi-threading + blocking IO 的性能更好,可能延迟还更大。select/epoll 的优势并不是对于单个连接能处理得更快,而是在于能处理更多的连接

  1. 信号驱动 I/O 模型(同步非阻塞)
    老李去火车站买票,给售票员留下电话,有票后,售票员电话通知老李,然后老李去火车站交钱领票
    耗费:往返车站 2 次,路上 2 小时,免黄牛费 100 元
Signal Driven IO

首先允许 socket 进行信号驱动 I/O,并安装一个信号处理函数,进程继续运行并不阻塞。当数据准备好时,进程会收到一个 SIGIO 信号,可以在信号处理函数中调用 I/O 操作函数处理数据

  1. 异步 I/O 模型(异步非阻塞)
    老李去火车站买票,给售票员留下电话,有票后,售票员电话通知老李并快递送票上门
    耗费:往返车站 1 次,路上 1 小时,免黄牛费 100 元
Asynchronous IO

调用 aio_read 函数,告诉内核描述字,缓冲区指针,缓冲区大小,文件偏移以及通知的方式,然后立即返回。当内核将数据拷贝到缓冲区后,再通知应用程序

异步 I/O 模型使用了 Proactor 设计模式实现了这一机制

五种 I/O 模型比较

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