前言

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

对以上的两个过程以及操作系统的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. Java并发之AQS原理剖析

    概述: AbstractQueuedSynchronizer,可以称为抽象队列同步器. AQS有独占模式和共享模式两种: 独占模式: 公平锁: 非公平锁: 共享模式: 数据结构: 基本属性: /** ...

  2. GO语言面向对象01---封装属性与创建对象的方法与工厂模式

    package main import "fmt" /* 面向过程编程:调度大量的变量.函数 ---------- 面向对象编程(OOP=Object Oriented Progr ...

  3. 太方便了!利用Python对批量Pdf转Word

    在wps或者office里面可以将pdf转word,不过只能免费转前面5页,超过5页就需要会员.今天教大家一个Python办公小技巧:批量Pdf转Word ,这样可以自由想转多少页都可以. 思路:这里 ...

  4. 主成分分析法(PCA)原理和步骤

    主成分分析法(PCA)原理和步骤 主成分分析(Principal Component Analysis,PCA)是一种多变量统计方法,它是最常用的降维方法之一,通过正交变换将一组可能存在相关性的变量数 ...

  5. CUDA 内存统一分析

    CUDA 内存统一分析 关于CUDA 编程的基本知识,如何编写一个简单的程序,在内存中分配两个可供 GPU 访问的数字数组,然后将它们加在 GPU 上. 本文介绍内存统一,这使得分配和访问系统中任何处 ...

  6. python+selenium基础篇,弹窗处理

    1.弹窗如下图所示 2.处理方法 from selenium.webdriver.common.action_chains import ActionChains#导入鼠标操作包 from selen ...

  7. springcloud webflux

    文章很长,建议收藏起来,慢慢读! 疯狂创客圈为小伙伴奉上以下珍贵的学习资源: 疯狂创客圈 经典图书 : <Netty Zookeeper Redis 高并发实战> 面试必备 + 大厂必备 ...

  8. Java 垃圾回收机制,13张图给你讲清楚

    什么是自动垃圾回收? 第一步:标记 第二步:清除 压缩 为什么需要分代垃圾收集? JVM 分代 世代垃圾收集过程 什么是自动垃圾回收? 自动垃圾回收是一种在堆内存中找出哪些对象在被使用,还有哪些对象没 ...

  9. 合宙Luat | Cat.1 Socket数据收不到?学会两招不掉线

    1 服务器收不到Socket数据的原因 Socket是大家使用Cat.1模块常用的功能之一,但Cat.1模块不是直接跟服务器连接,而是通过NAT(即网络地址转换)与服务器连接. 一个会话建立后会在NA ...

  10. 【二分 贪心】覆盖问题 BZOJ1052 HAOI2007

    覆盖问题 bzoj1052 题目来源:HAOI 2007 题目描述 某人在山上种了N棵小树苗.冬天来了,温度急速下降,小树苗脆弱得不堪一击,于是树主人想用一些塑料薄膜把这些小树遮盖起来,经过一番长久的 ...