【网络IO系列】IO的五种模型,BIO、NIO、AIO、IO多路复用、 信号驱动IO

时间:2023-02-19 12:04:13

前言

在上一篇文章中,我们了解了操作系统中内核程序和用户程序之间的区别和联系,还提到了内核空间和用户空间,当我们需要读取一条数据的时候,首先需要发请求告诉内核,我需要什么数据,等内核准备好数据之后再从内核空间拷贝到用户空间 注意加粗的部分,这两个阶段至关重要

对以上的两个过程以及操作系统的IO流程不了解的,请务必左转去看上一篇文章,上篇文章中是学习IO的基础知识,只有把上一篇文章的内容看懂了,对于后续的IO几种模型的学习和理解才会更为深刻,上一篇文章可以说是整个IO中的基石级别的知识。

文章链接 【网络IO系列】 预备知识 操作系统之内核程序和用户程序

IO的五种模型

我们回到正题,从上篇文章我们知道,当我们进行一次IO的时候,是要经过这两个阶段的,分别是

第一阶段 :等待内核准备数据

第二阶段:数据从内核空间拷贝到用户空间

这两个阶段则决定着IO的各种模型的类型,通过这两个阶段,可以将IO模型分成五种,分别是

  • 阻塞式IO(BIO)
  • 非阻塞式IO(NIO)
  • IO多路复用
  • 信号驱动IO
  • 全异步IO(AIO)

阻塞

说到阻塞,在这里想先明确一下,什么是阻塞。从线程或者进程的角度来看,阻塞就是因为当前执行的这个线程,暂时的失去了CPU的执行权,被挂起等待下一次线程的调度或者线程被唤醒。如果是具体到我们的IO的话,则可以理解为,阻塞的时候你需要等待,等到数据准备好或者执行结果返回,才能继续下一步的操作,不然只能一直等待下去。而非阻塞,则是,即便数据没有准备好,或者执行没有完成,你也可以去做其他的事情。

  举个例子,比如说你出门排队买东西,假如你没有带手机,那你只能老老实实排队等轮到你,在这之前,你除了排队这件事之外,其他什么事情都干不了也不允许干,这个时候你就是阻塞的,因为你只能做排队这一件事。那么同样是排队,这一次你带了手机,那你排队的时候,可以边玩手机边排队,这个时候你就是非阻塞的。

接下来让我们对应到上面的两个阶段,如果等待内核准备数据的时候,执行线程可以去做其他的事,那么在第一阶段就是非阻塞的,否则就是阻塞的。如果在数据从内核空间拷贝到用户空间阶段,执行线程可以去干其他的事,那么第二阶段就是非阻塞的,否则就是阻塞的。

阻塞式IO(BIO)

阻塞式IO,是在两个阶段都阻塞的一种IO模型,用户发起IO请求,在等待数据和数据拷贝阶段,都会被阻塞,只有这两个阶段都完成了,才能去做下一阶段的事情。

  就像是你没带手机去吃饭,你跟老板说要吃鱼香肉丝,然后要等老板做好菜(准备数据),然后从厨房把菜端到你面前(数据拷贝),这两个阶段你都只能等着,什么事都干不了。

由于BIO阻塞时间长,因此相对性能就会较低,所以现在用的相对也比较少了。

非阻塞IO(NIO)

非阻塞IO,可以看作是半阻塞IO,因为他在第一阶段数据准备阶段不阻塞,第二阶段数据拷贝阶段阻塞,当用户发出IO请求的时候,会有一个线程去询问内核数据准备好了吗,一直问一直问,在这期间,用户主进程可以去干其他的事,等数据准备好了,到了第二阶段,这个时候,用户线程就要执行拷贝数据,这个时候是阻塞的。这种方式的缺点就是反复的轮训去询问内核数据好了没,是很消耗CPU资源的。

  就像是你带手机去吃饭,你点好菜之后,你可以一直问老板,我的菜好了没,老板说没有,问完之后就可以继续玩手机继续等,继续问。等到有一次你问,老板我的菜好了吗,老板说好了,你自己过来端一下。(注意,问菜好没有的,得是你自己问,这家NIO店的老板比较高冷,菜好了你不问他是不会主动告诉你的,这就是NIO的特点,数据准备就绪是用户线程主动发出的询问),这个时候菜好了,你要自己去端(数据拷贝),这个端菜的阶段,你期间啥都干不了,也不能玩手机,所以NIO的第二个阶段是阻塞的。

说到这里我们可以看出BIO和NIO之间的区别了,一个是傻等老板做菜给你,期间你什么都干不了,一个是自己主动询问老板,菜好了没,期间你可以玩手机,或者干其他的,相比BIO,NIO的效率就高了很多。当然,你可能会问了,为啥菜好没好,还得我自己主动去问,这也太不人性化了,确实,这个问题我们想得到,计算机的科学界大师们自然也想得到,于是为了解决这个问题,于是出现了信号驱动IO和IO多路复用。

IO多路复用

通过我们上面对NIO的了解,我们可以知道,NIO多少存在着一些不够好的地方,因为反复的轮训也是很消耗cpu资源的。如果饭店的人少还好说,但是如果饭店人多起来了,比如说来了几百个人,那每个人时不时就要发起一次询问请求,那老板管不过来啊,cpu占用率也会非常高。于是,IO多路复用就出现了,IO多路复用可以说是目前用的最多的一个IO模型,在不同的操作系统内核,也有不同的实现方式,在这篇文章中,我们IO多路复用的大概思想,至于详细介绍,后面会用一篇文章来详细的介绍IO多路复用

IO多路复用,实际上,是通过IO请求都通过一个selector来管理,用户进程的IO请求就不直接发给内核处理程序了,而是注册到这个selector上面,由selector来告诉内核需要哪些数据,然后定时的去查询内核程序,我这个selector上需要的数据,有哪些准备好了,然后再由selector告诉那些准备好了的用户线程,让该用户线程去拷贝数据。在非阻塞IO中,不断地询问状态时通过用户线程去进行的,而在IO多路复用中,询问每个状态是内核在进行的,在IO请求非常多的时候,这个效率要比用户线程轮询要高的多。

  就像是你带手机去饭店吃饭,现在这家饭店的老板由于生意越来越好,人越来越多,他有点管理不过来了,于是他请了几个服务员(selector)协助管理,然后现在饭店客户的点餐都是告诉服务员,我需要什么菜,然后服务员把xx桌客户的菜,记在自己的单子上。然后服务员告诉厨房他这个单子上需要哪些菜,让厨房去做。。服务员定时问厨房看看有哪些菜已经准备好了,然后告知15号桌和89号桌客人你们的菜已经好了,请来前台端一下,然后你就去前台端菜,端菜的阶段是阻塞的。

来比较一下IO多路复用和NIO,我们可以发现,当IO请求多的时候,IO多路复用效率无疑是更高的。因为对于用户线程来说,你点完菜就可以一直玩手机了,不用因为一直问老板而分心分神,耽误你打王者,因为菜好了,服务员会通知你

信号驱动IO

通过我们上面两种IO模型的了解,我们可以知道,不管是NIO还是IO多路复用,本质上还是轮询,只不过NIO是用户线程轮询,IO多路复用是委托给selector让他来轮询,那有没有什么办法能让内核主动通知数据好了没。所以,信号驱动IO出现了。信号信号,顾名思义,就是会有一个信号通知你数据已经准备好了,不用你一直去问。信号驱动IO,用户线程发出一个请求告诉内核我需要什么数据,数据准备好了你告诉我一声,然后内核就会记录下这个请求,内核准备好了之后会主动通知用户线程去执行拷贝数据,数据拷贝阶段是阻塞的,需要等数据拷贝完才能做其他的事。

   就像是你带手机去吃饭,你点好菜之后,你就只管玩手机了,啥也不用管,就等老板通知你,期间你想干啥就干啥,等到菜准备好了,老板会大声说(内核主动通知用户进程),xxx你的鱼香肉丝已经准备好了,请过来前台端一下,这个时候你要自己去端(数据拷贝),这个端菜的阶段,你期间啥都干不了,也不能玩手机,所以信号驱动IO的第二个阶段也是阻塞的。

我们对比信号驱动IO和NIO,可以发现最重要的区别就是NIO是用户主动询问内核数据好了吗,而信号驱动IO是内核主动通知用户数据已经好了,这就改善了上面说的NIO的问题。

全异步IO

全异步IO是最理想的一种IO模型,所谓全异步IO就是,用户进程发起了一个IO请求,接下来可以干其他的事了,不需要等内核准备好,也不需要执行数据拷贝,数据异步拷贝到用户空间之后,用户进程直接拿来用就行了,这两个阶段都是由内核自动完成。完全不用用户线程操心这些事。

前面四种IO模型实际上都属于同步IO,只有最后一种才是是真正的异步IO,因为不管是是IO多路复用还是信号驱动,IO操作的第2个阶段都会让用户线程阻塞,也就是内核进行数据拷贝的过程都会让用户线程阻塞。

  举个例子就像是,你去饭店吃饭,点好餐之后,你就可以玩手机了,饭菜做好之后,服务员会把饭菜端到你的面前,你也不需要自己去端,你需要点餐和吃饭就行了,其他的你都不用管。简单来说,就是发出请求之后,只需要等待数据完成直接使用,等待期间,你可以做其他的事。整个过程完全的异步,体验最好。

全异步IO虽然非常牛逼,但是现在还不是很成熟,支持全异步IO的操作系统和框架也还不是很多,所以用的也不是很多。我们只需要了解一下就行了

总结

我们这篇文章讲了五种IO模型的思想,并且每种模型我们都通过一个通俗易懂的例子,来描绘其过程。相信你看完之后一定有收获。其中比较重要的两种是NIO和IO多路复用,这是目前来说用的最多的两种,后面的篇幅,会专门的讲这两种模型,尤其是IO多路复用,在不同的OS上,又有select,poll,和epoll方式。等下一篇文章,我们将会细讲。

【网络IO系列】IO的五种模型,BIO、NIO、AIO、IO多路复用、 信号驱动IO的更多相关文章

  1. JAVA-IO模型(BIO,NIO,AIO)

    基本概念 阻塞和非阻塞 阻塞是进行读写时, 如果当时没有东西可读,或者暂时不可写, 程序就进入等待, 直到有东西可读或者可写为止 非阻塞是如果没有东西可读, 或者不可写, 读写函数马上返回, 而不会等 ...

  2. 温故知新-java的I/O模型-BIO&NIO&AIO

    文章目录 摘要 传统的BIO编程 伪异步I/O编程 NIO编程 AIO编程 几种IO模型的对比 netty 参考 你的鼓励也是我创作的动力 Posted by 微博@Yangsc_o 原创文章,版权声 ...

  3. IO 的五种模型是什么

    目录 前言 用户空间和内核空间 IO 五种模型 阻塞型 IO 非阻塞 IO IO 多路复用 信号驱动 IO 异步 IO 总结 阻塞和非阻塞 同步与异步 前言 我们经常看到阻塞/非阻塞,同步/异步这两组 ...

  4. 2. 彤哥说netty系列之IO的五种模型

    你好,我是彤哥,本篇是netty系列的第二篇. 欢迎来我的公从号彤哥读源码系统地学习源码&架构的知识. 简介 本文将介绍linux中的五种IO模型,同时也会介绍阻塞/非阻塞与同步/异步的区别. ...

  5. IO的五种模型

    为了区分IO的五种模型,下面先来看看同步与异步.阻塞与非阻塞的概念差别. 同步:所谓同步,就是在发出一个功能调用时,在没有得到结果之前,该调用就不返回.按照这个定义,其实绝大多数函数都是同步调用(例如 ...

  6. Linux 网络编程的5种IO模型:信号驱动IO模型

    Linux 网络编程的5种IO模型:信号驱动IO模型 背景 上一讲 Linux 网络编程的5种IO模型:多路复用(select/poll/epoll) 我们讲解了多路复用等方面的知识,以及有关例程. ...

  7. I/O模型系列之三:IO通信模型BIO NIO AIO

    一.传统的BIO 网络编程的基本模型是Client/Server模型,也就是两个进程之间进行相互通信,其中服务端提供位置信息(绑定的IP地址和监听端口),客户端通过连接操作向服务端监听的地址发起连接请 ...

  8. 图解I/O的五种模型

    1.1 五种I/O模型 1)阻塞I/O 2)非阻塞I/O 3)I/O复用 4)事件(信号)驱动I/O 5)异步I/O 1.2 为什么要发起系统调用? 因为进程想要获取磁盘中的数据,而能和磁盘打交道的只 ...

  9. linux第7天 I/O的五种模型, select

    服务器端避免僵尸进程的方法: 1)通过忽略SIGCHLD信号,解决僵尸进程 signal(SIGCHLD, SIG_IGN) 2)通过wait方法,解决僵尸进程 signal(SIGCHLD, han ...

随机推荐

  1. Sql语句复习

    1.两张表A,B 其中A表中字段1,字段2,字段3要迁移到B表中字段4,字段5,字段6,迁移后B表的字段7 全赋值为123: insert into B(字段4,字段5,字段6,字段7) select ...

  2. JAVA IO 详解2

    Java 流在处理上分为字符流和字节流.字符流处理的单元为 2 个字节的 Unicode 字符,分别操作字符.字符数组或字符串,而字节流处理单元为 1 个字节,操作字节和字节数组. Java 内用 U ...

  3. 社交系统ThinkSNS+ 发布通知!

    社交系统ThinkSNS 最新版本ThinkSNS+将于7月15日正式发布开源版本web+H5,同时发布Android APP和iOS APP.我们将告别内测阶段,正式对外发布. 没错,你们没看错,就 ...

  4. [DeeplearningAI笔记]Batch NormalizationBN算法Batch归一化_02_3.4-3.7

    Batch Normalization Batch归一化 觉得有用的话,欢迎一起讨论相互学习~Follow Me 3.4正则化网络的激活函数 Batch归一化会使你的参数搜索问题变得很容易,使神经网络 ...

  5. XVII Open Cup named after E.V. Pankratiev. GP of Siberia, Division 1

    1. Ski race 枚举枚举倍数判断即可.时间复杂度$O(n\log m)$. #include<cstdio> #include<algorithm> using nam ...

  6. vue批量验证提交表单的数据是否合规

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  7. https&colon;&sol;&sol;*&period;com&sol;questions&sol;40949967&sol;running-storm-from-intellij-nimbus-error

    https://*.com/questions/40949967/running-storm-from-intellij-nimbus-error 0down votefavo ...

  8. PHP编译安装时常见错误解决办法,php编译常见错误

    PHP编译安装时常见错误解决办法,php编译常见错误 1.configure: error: xslt-config not found. Please reinstall the libxslt & ...

  9. HIVE之 Sqoop 1&period;4&period;6 安装、hive与oracle表互导

    1. sqoop数据迁移 1.1 概述 sqoop是apache旗下一款“Hadoop和关系数据库服务器之间传送数据”的工具. 导入数据:MySQL,Oracle导入数据到Hadoop的HDFS.HI ...

  10. Chrome 鼠标左键-新标签打开

    改chrome设置 1.打开google搜索主页2.打开右下角Settings选项->Search Settings3.找到where results open选项4.把Open each se ...