【Linux】五种IO模型

文章目录

  • 1. IO基本概念
  • 2. 五种IO模型
    • 2.1 五个钓鱼的例子
    • 2.2 五种IO模型
      • 2.2.1 阻塞IO
      • 2.2.2 非阻塞IO
      • 2.2.3 信号驱动IO
      • 2.2.4 IO多路转接
      • 2.2.5 异步IO

1. IO基本概念

认识IO

IO就是输入和输出,在冯诺依曼体系结构中,将数据从输入设备拷贝到内存就叫输入,将输出将内存拷贝到输出设备就叫输出。
在这里插入图片描述

  • 对文件进行的读写操作本质就是一种IO,文件IO对应的外设就是磁盘。
  • 对网络进行的读写操作本质也是一种IO,网络IO对应的外设就是网卡。

OS如何得知外设中有数据可读?

输入就是操作系统将数据从外设拷贝到内存的过程,操作系统一定要通过某种方法得知特定外设上是否有数据就绪。

  • 并不是操作系统想要从外设中取数据时外设中就一定有数据,比如可能用户正在访问服务器,当用户的请求报文发出之后就需要在网卡中读取服务器发来的响应报文,但此时服务器可能还没有收到我们的报文,或是正在对收到的包文进行数据分析。
  • 但操作系统并不会去主动检测外设上是否有数据就绪,这样会降低操作系统的工作效率,因为大部分情况下外设当中都是没有数据的,如果操作系统去主动检测外设上是否有数据那么大部分情况下这样的操作都是徒劳的。
  • 操作系统实际采用的是中断的方式来得知外设上是否有数据就绪的,当某个外设上面有数据就绪时,该外设就会向CPU的中断控制器中发送中断信号,中断控制器再根据产生的中断信号的优先级顺序发送给CPU。
  • 每一个中断信号都有一个对应的中断处理程序,存储中断信号和中断处理程序映射关系的表叫做中断向量表,当CPU收到某个中断信号时就会自动停止正在运行的程序,然后根据该中断向量表执行该中断信号对应的中断处理程序,处理完毕后再返回被暂停的程序继续运行。

需要注意的是,CPU不直接和外设打交道指的是在数据层面上,而外设其实可以直接将某些控制信号发给CPU当中的某些控制器的。

OS如何处理从网卡中拿到的数据包?

操作系统任何时刻可能都会收到大量的数据包,因此操作系统必须将这些数据包管理起来。所谓的管理就是“先描述,再组织”,在内核当中有一个结构叫做sk_buff,该结构就是用来管理和控制接收或者发送数据包的信息的。

这是一个简化版的sk_buff结构:
在这里插入图片描述

  • 当操作系统从网卡中读取到了一个数据包之后,就会定义出一个sk_buff结构,然后用sk_buff结构当中的data指针指向这个读取到的数据包,并将这个定义出来的sk_buff结构与其他sk_buff结构用双链表的形式组织起来,这样操作系统对各个数据包的管理就变成了对双链表的增删查改了。
  • 接下来我们需要将读取上来的数据包交给最底层的链路层处理,进行链路层的解包和分用,此时就是让sk_buff结构当中的mac_header指针指向最初的数据包,然后向后读取链路层的报头,剩下的就是需要交给网络层的有效载荷了,此时便完成了链路层的解包。
  • 这时链路层就需要将有效载荷向上交付给网络层进行解包和分用了,这里所说的向上交付只是形象的说法,实际向上交付并不是要将数据从链路层的缓冲区拷贝到网络层的缓冲区,而是只需要让sk_buff结构当中的network_header指针指向数据包中链路层之后的数据即可,然后继续向后读取网络层的报头,便完成了网络层的解包。
  • 然后对传输层的处理同理,只需让sk_buff结构当中的transport_header指针指向数据包中网络层报头之后的数据,然后向后读取传输层的报头,便完成了传输层的解包。
  • 传输层解包之后就可以根据具体的使用的传输层协议,对应将剩下的数据宝贝到TCP或者UDP的接收缓冲区供用户读取即可。
    在这里插入图片描述
    发送数据时对数据进行封装也是同样的道理,就是依此在数据前面拷贝上对应的报头,最后再将数据发送出去(UDP)或者拷贝到发送缓冲区(TCP)即可。也就说,数据包在封装和解包的过程中,本质数据的存储位置是没有发送变化的,我们实际只是在用不同的指针对数据进行操作而已。

但内核中的sk_buff其实并没有那么简单,设计远比上面说的复杂。

  • 一方面,为了保证高效的网络报文处理效率,这就要求sk_buff的结构也必须高效。
  • 另一方面,sk_buff结构需要被内核协议当中的各个协议共同使用,因此sk_buff必须能够兼容所有的网络协议。

因此sk_buff结构其实是非常复杂的。

高效的IO

IO主要分两步:

  1. 第一步是等,等待IO就绪。
  2. 第二步是拷贝,将数据拷贝到内存或者外设。

任何IO的过程,都包含等和拷贝这两个步骤,在实际的应用场景中“等”消耗的时间远比“拷贝”消耗的时间多,因此要让IO变得高效,就要尽可能减少“等”的时间。

2. 五种IO模型

2.1 五个钓鱼的例子

IO的过程其实和钓鱼是非常类似的。

  • 钓鱼的过程同样分为“等”和“拷贝”两个步骤,只不过这里的“等”是等鱼上钩,“拷贝”指的是当鱼上钩后将鱼从河里“拷贝”到我们的鱼桶当中。
  • IO时等消耗的时间往往要比拷贝消耗的多,钓鱼也符合这个特点,钓鱼时哦我们大部分时间都在等待鱼上钩,而当鱼上钩后只需要一瞬间就能将鱼“拷贝”上来。

在了解五种IO模型之前,我们先看看什么样的钓鱼方式才是最高效的。

  1. 张三:拿了1个鱼竿,将鱼钩抛入水中就死死盯着浮漂,什么也不做,让有鱼上钩后再将鱼钓上来。
  2. 李四:拿了1个鱼竿,将鱼钩抛入水中后就去做其他事情,然后定期观察浮漂,如果有鱼上钩则挥动鱼竿将鱼钓上来,否则进行去做其他事情。
  3. 王五:拿了1个鱼竿,将鱼钩抛入水后在鱼竿顶部绑一个铃铛,然后就去做其他事情,如果铃铛响了就挥动鱼竿将鱼钓上来。
  4. 赵六:拿了00个鱼竿,将100个鱼竿抛入水中就定期观察这100个鱼竿的浮漂,如果某个鱼竿有鱼上钩则挥动对应的鱼竿将鱼钓上来。
  5. 田七:田七是一个有钱的老板,他给了自己的司机一个桶,一个电话,一个鱼竿,当司机去钓鱼,当鱼桶装满的时候再告诉田七来拿鱼,而田七自己则开车去做其他事情了。

张三、李四、王五的钓鱼效率是否一样?为什么?

本质都是一样的。

  • 首先它们的钓鱼方式都是一样的,都是等于上钩,然后再将鱼钓上来。
  • 其次,因为它们每个人都是拿的一根鱼竿。

因此他们三个的钓鱼效率本质是一样的,只不过他们的等待方式不同而已,张三是死等,李四是定期检测浮漂,王五是通过铃铛来判断鱼是否上钩。

需要注意的是,这里问的是他们的钓鱼效率是否一样,而不是问他们整体谁做的事更多,如果说整体做事情的量的话,那一定是王五做的最多,李四次之,张三最少。

与张三、李四、王五相比,赵六的钓鱼效率非常高。

高效的钓鱼就是要减少等的时间,增加拷贝的时间,赵六可以将等的时间重合,一次等待多个鱼竿有鱼上钩。

毫无疑问,赵六的钓鱼效率是四个人中最高的。

如何看待田七的钓鱼方式?

田七本人并没有参数整个钓鱼的过程,他只是发起了钓鱼的任务,真正钓鱼的是司机,田七在钓鱼期间可能就去做其他事情了。

如果将钓鱼看作是一种IO的话,前面四个人的钓鱼方式就是同步IO,田七的钓鱼方式就是异步IO。

2.2 五种IO模型

实际上上面所说的五种钓鱼方式分别对应五种IO模型

  1. 张三这种死等的方式叫做阻塞IO
  2. 李四这种定时检测的方式叫做非阻塞IO
  3. 王五这种通过设置铃铛的方式叫做信号驱动IO
  4. 赵六这种一次等待多个鱼竿的方式叫做IO多路转接
  5. 田七这种让别人帮自己钓鱼的方式就是异步IO

通过上面的例子我们可以看到,阻塞IO、非阻塞IO、信号驱动IO不能提高IO的效率,但是非阻塞IO和信号驱动IO能提高整体做事的效率。

其实,这个钓鱼场景中的各个事务都能与IO当中的相关概念对应起来,比如这里钓鱼的河对应就是内核,这里的每一个人都说进程或者线程,鱼竿对应的就是文件描述符或套接字,装鱼的桶对应的就是用户缓冲区。

2.2.1 阻塞IO

阻塞IO就是将内核将数据准备好之前,系统会一直等待。
在这里插入图片描述
阻塞IO是最常见的IO模型,所有的套接字,默认都是阻塞方式。

  • 比如调用recvfrom函数从某个套接字读取数据时,可能是底层数据还没有准备好,此时就需要等待数据就绪,当数据就绪之后再将数据从内核拷贝到用户空间,最后recvfrom函数才能返回。
  • 在recvfrom函数等待数据就绪期间,在用户看来该进程或者线程就阻塞住了,本质就是操作系统将该进程或线程的状态设置为了某种非R状态,然后将其放入等待队列当中,当数据就绪后操作系统再将其从等待队列中唤醒,然后该进程或线程再将数据从内核拷贝到用户空间。

以阻塞方式进行IO操作的进程或者线程,在“等”和“拷贝”期间都不会返回,在用户看来好像就是阻塞住了,因此我们称之为阻塞IO。

2.2.2 非阻塞IO

非阻塞IO就是,如果内核还未将数据准备好,系统调用仍然会直接返回,并且返回EWOULDBLOCK错误码。
在这里插入图片描述
非阻塞IO往往需要程序员以循环的方式反复尝试读写文件描述符,这个过程称为轮询,这对CPU来说是一种很大的浪费,一般只有在特定场景下才使用。

  • 比如当调用recvfrom函数以非阻塞方式从某个套接字上读取数据时,如果底层数据还没有准备好,那么recvfrom函数会立马错误返回,而不会让该进程或线程进行阻塞等待。
  • 因为没有读取的数据,因此该进程或线程后续还需要继续调用recvfrom函数,检测底层数据是否就绪,如果没有就绪数据,继续返回,直到就绪之后,再将数据从内核拷贝到用户空间然后成功返回。
  • 每次调用recvfrom函数读取数据时,不管底层有没有就绪,recvfrom函数都会直接返回,在用户看来该进程或线程就没有被阻塞住,称为非阻塞IO。

阻塞IO和非阻塞IO的区别在于,阻塞IO当数据没有就绪时,后续检测数据是否就绪是由操作系统发起的,而非阻塞IO当数据没有就绪时,后续检测数据是否就绪的工作是由用户发起的。

2.2.3 信号驱动IO

信号驱动IO就是内核将数据准备好的时候,使用SIGIO信号通知程序进行IO操作。
在这里插入图片描述
当底层数据就绪的时候会向当前进程或线程递交SIGIO信号,因此可以通过signal或者sigaction函数将SIGIO的信号处理程序定义为需要进行的IO操作,当底层数据就绪时就会执行对应的IO操作。

  • 比如我们需要调用recvfrom函数从某个套接字上读取数据,那么就可以将操作定义为SIGIO的信号处理程序。
  • 当底层数据就绪时,操作系统就会递交SIGIO信号,那么此时就会自动执行我们定义的信号处理程序,仅需将数据从内核拷贝到用户空间。

信号的产生是异步的,但信号驱动IO是同步IO的一种。

  • 我们说信号的产生是异步的,因为信号在任何时刻都可能产生。
  • 但信号驱动是同步IO的一种,因为当底层数据就绪时,当前进程或线程就需要停下正在做的事情,转而进行数据的拷贝操作,因此当前进程或线程仍然需要参与IO过程。

判断一个IO过程是同步的还是异步的,本质就是看当前进程或线程是否需要参与IO过程,如果要参与那么就是同步IO,否则就是异步IO。

2.2.4 IO多路转接

IO多路转接也叫IO多路复用,能够同时等待多个文件描述符的等待装填。
在这里插入图片描述
IO多路转接的思想:

  • 因为IO过程分为“等”和“拷贝”两个步骤,因此我们使用的recvfrom等接口的底层实际上都做了两件事,第一件事就是当数据不就绪时需要等,第二件事就是当数据就绪后需要进行拷贝。
  • 虽然recvfrom等接口也有等的能力,但这些接口一次只能等一个文件描述符上的数据或者空间就绪,这样IO效率太低了。
  • 因此系统为我们提供了三组接口,分别叫做select、poll、epoll,这些接口的核心工作就是等,我们可以将所有等的工作都交给这些多路转接的接口。
  • 因为这些多路转接接口是一次等多个文件描述符的,因此能够将等的时间进行重叠,当数据就绪之后再调用对应的recvfrom等函数进行数据的拷贝,此时这些函数就能够直接进行拷贝,而不需要再进行等操作了。

2.2.5 异步IO

异步IO就是数据拷贝完成之后,等待应用程序。
在这里插入图片描述

  • 进行异步IO需要调用一些异步IO的接口,异步IO接口调用后会立马返回,因为异步IO不需要你进行“等”和“拷贝”的操作,这两个操作都由操作系统完成,你要做的只是发起IO。
  • 当IO完成后操作系统会通知应用程序,因此进行异步IO的进程或线程并不参与IO的所有细节。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/58916.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

STM32使用HAL库中外设初始化MSP回调机制及中断回调机制详解

STM32使用HAL库之Msp回调函数 1.问题提出 在STM32的HAL库使用中,会发现库函数大都被设计成了一对: HAL_PPP/PPPP_Init HAL_PPP/PPPP_MspInit 而且HAL_PPP/PPPP_MspInit函数的defination前面还会有__weak关键字 上面的PPP/PPPP代表常见外设的名称为…

什么是OCR?OCR技术详解

光学字符识别(Optical Character Recognition)简称为“OCR”。ORC是指对包含文本资料的图像文件进行分析识别处理,获取文字及版面信息的技术。 一般包括以下几个过程: 1.图像输入 针对不同格式的图像,有着不同的存储格式和压缩方式。目前&…

JMeter 的使用

文章目录 1. JMeter下载2. JMeter的使用2.1 JMeter中文设置2.2 JMeter的使用2.2.1 创建线程组2.2.2 HTTP请求2.2.3 监听器 1. JMeter下载 官网地址 https://jmeter.apache.org/download_jmeter.cgi https://dlcdn.apache.org//jmeter/binaries/apache-jmeter-5.6.2.zip 下载解…

[JAVAee]锁策略

目录 乐观锁与悲观锁 乐观锁 乐观锁的冲突检测 悲观锁 读锁与写锁 重量级锁与轻量级锁 重量级锁 轻量级锁 自旋锁 公平锁与非公平锁 可重入锁与不可重入锁 乐观锁与悲观锁 乐观锁 在乐观锁中,假设数据并不会发生冲突,在正式提交数据时会对数据进行冲突检测,如果发…

ARM 常见汇编指令学习 9 - 缓存管理指令 DC 与 IC

文章目录 ARM64 DC 与 IC 指令 上篇文章:ARM 常见汇编指令学习 8 - dsb sy 指令及 dsb 参数介绍 ARM64 DC 与 IC 指令 AArch64指令集中有两条关于缓存维护(cache maintenance)的指令,分别是IC和DC。 IC 是用于指令缓存操作&…

项目经理必读:领导风格对项目成功的关键影响

引言 项目经理作为一个领导者的角色,他们需要协调各方资源,管理团队,推动项目的进行。为了完成这些任务,项目经理必须具备各种领导风格的灵活性,以应对项目中的各种变数和挑战。在这篇文章中,我们将讨论领…

SpringBoot 项目创建与运行

一、Spring Boot 1、什么是Spring Boot?为什么要学 Spring Boot Spring 的诞生是为了简化 Java 程序的开发的,而 Spring Boot 的诞生是为了简化 Spring 程序开发的。 Spring Boot 翻译一下就是 Spring 脚手架 盖房子的这个架子就是脚手架,…

LeetCode 25题:K个一组翻转链表

题目: 给你链表的头节点 head ,每 k 个节点一组进行翻转,请你返回修改后的链表。 k 是一个正整数,它的值小于或等于链表的长度。如果节点总数不是 k 的整数倍,那么请将最后剩余的节点保持原有顺序。 你不能只是单纯…

web爬虫第五弹 - JS逆向入门(猿人学第一题)

0- 前言 爬虫是一门需要实战的学问。 而对于初学者来说,要想学好反爬,js逆向则是敲门砖。今天给大家带来一个js逆向入门实例,接下来我们一步一步来感受下入门的逆向是什么样的。该案例选自猿人学练习题。猿人学第一题 1- 拿到需求 进入页面…

在登录界面中设置登录框、多选项和按钮(HTML和CSS)

登录框(Input框)的样式: /* 设置输入框的宽度和高度 */ input[type"text"], input[type"password"] {width: 200px;height: 30px; }/* 设置输入框的边框样式、颜色和圆角 */ input[type"text"], input[type&q…

flutter:占位视图(骨架屏、shimmer)

前言 有时候打开美团,在刚加载数据时会显示一个占位视图,如下: 那么这个是如何实现的呢?我们可以使用shimmer来开发该功能 实现 官方文档 https://pub-web.flutter-io.cn/packages/shimmer 安装 flutter pub add shimmer示例…

Pytest+Allure+Excel接口自动化测试框架实战

1. Allure 简介 简介 Allure 框架是一个灵活的、轻量级的、支持多语言的测试报告工具,它不仅以 Web 的方式展示了简介的测试结果,而且允许参与开发过程的每个人可以从日常执行的测试中,最大限度地提取有用信息。 Allure 是由 Java 语言开发…

【laravel+vue2 】医院信息化手术麻醉临床信息管理系统源码

近年来,医院信息化成为医院领域的推广重点,HIS、LIS、PACS、EMR等信息系统的相继出现,显著提高了医院业务的运行效率。手术麻醉系统作为医院信息系统的一部分,由监护设备数据采集系统和麻醉信息管理系统两个子系统组成。 一、医院…

复亚智能打造全新云平台:让无人机任务管理更智能、更简单

复亚智能全新升级的MindView云平台,对航线规划、任务管理、自动飞行、数据管理等各个环节开展可视化、数字化、智能化监管,从任务到结果的“看得清”、“管得住”、“查得准”,带来更轻松的操作,改善作业效率、安全保障和用户体验…

抖音seo矩阵系统源码搭建开发详解

抖音SEO矩阵系统是一个用于提高抖音视频在搜索引擎排名的工具。如果你想开发自己的抖音SEO矩阵系统,以下是详细的步骤: 开发步骤详解: 确定你需要的功能和算法 抖音SEO矩阵系统包含很多功能,比如关键词研究、内容优化、链接建设、…

SQL基础复习与进阶

SQL进阶 文章目录 SQL进阶关键字复习ALLANYEXISTS 内置函数ROUND(四舍五入)TRUNCATE(截断函数)SEILING(向上取整)FLOOR(向下取整)ABS(获取绝对值)RAND&#x…

HTML 初

前言 HTML的基本骨架 HTML基本骨架是构建网页的最基本的结果。 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0">…

8月4日上课内容 nginx(重要内容,面试必问)

国外主要还是apache nginx高性能、轻量级的web服务软件。 nginx的特点 1、稳定性高。&#xff08;没有apache稳定&#xff09; 常用版本 1.12 1.20 1.22 2、系统资源消耗低。&#xff08;处理http请求的并发能力很高&#xff0c;单台服务器可以处理30000-50000个并发请求。…

【无标题】一篇文章带你彻底理解Java ArrayList数据结构详解

一篇文章带你彻底理解Java ArrayList数据结构详解 基本概念&#xff1a; ​ **之前创建数组的时候&#xff0c;需要声明提前声明数组的大小&#xff0c;**ArrayList是一个可以动态修改的数组&#xff0c;与普通数组的区别就是没有固定大小的限制&#xff0c;它会动态调整长度…

2023华数杯数学建模竞赛C题思路解析

如下为&#xff1a;2023华数杯数学建模竞赛C题 母亲身心健康对婴儿成长的影响 的思路解析 C题 母亲身心健康对婴儿成长的影响 母亲是婴儿生命中最重要的人之一&#xff0c;她不仅为婴儿提供营养物质和身体保护&#xff0c;还为婴儿提供情感支持和安全感。母亲心理健康状态的不…