Linux高级 I/O

news/2024/11/28 11:48:53/

目录

一、五种I/O模型 

1. 阻塞式I/O

2. 非阻塞式I/O

3. I/O复用(多路转接)

4. 信号驱动式I/O

5. 异步I/O

二、五种I/O模型的比较 

三、I/O复用典型使用在下列网络应用场合


一、五种I/O模型 

  • 阻塞式I/O
  • 非阻塞式I/O
  • I/O复用(多路转接)
  • 信号驱动式I/O
  • 异步I/O

I/O我们并不陌生,简单的说就是输入输出;对于一个输入操作通常包括两个不同的阶段:

  1. 等待数据准备好
  2. 从内核向进程复制数据

        对于一个套接字上的输入操作,第一步通常涉及等待数据从网络中到达,然后被复制到内核的某个缓冲区;第二步就是把数据从内核缓冲区复制到应用进程的缓冲区。

        注:我们以UDP数据报为例,来介绍这五个模型,主要是因为,数据准备好读取的概念比较简单,要么整个数据报已经收到,要么还没有。对于TCP而言,它是面向字节流的,存在水位线的概念,导致理解起来比较复杂。

        接下来我们都会先以一个简单的生活例子来解释这五种I/O模型,然后再对图例进行解释;

1. 阻塞式I/O

        最流行的I/O模型是阻塞式I/O模型,我们之前的博客中基本都采用的是阻塞式I/O(因为默认情况下所有的套接字都是阻塞的)。

生活中的例子:

        对于阻塞式I/O模型,你可以想象一下钓鱼的例子,假设张三就是在这种模型下进行钓鱼,张三带着一根鱼竿去钓鱼,他在完成所有准备工作后,一心一意的在岸边等待着鱼儿上钩,就像是阻塞了一样,直到鱼儿上钩后或者鱼竿坏了才会动作;

模型解释:

        对于上图给出的模型,进程调用recvfrom,其系统调用直到数据报到达且被复制到应用进程的缓冲区中或者发送错误才返回。最常见的错误是系统调用被信号中断。(进程就好比是张三,调用recvfrom不就是用鱼竿钓鱼嘛,数据报就好比是鱼儿,当数据报准备好并复制会后就好比鱼儿吃钩了)

2. 非阻塞式I/O

        对于非阻塞式I/O模型,就是进程把一个套接字设置成非阻塞,本质上就是在通知内核:当所有请求的I/O操作非得把本进程投入睡眠才能完成时,请不要把本进程投入睡眠,而是返回一个错误。

生活中的例子:

        非阻塞式I/O模型,也是钓鱼的例子,这次是李四在钓鱼。李四拿着一个鱼竿,他觉得张三钓鱼太累了(阻塞了),他将所有工作都完成后,定期的检测水面是否有动静,如果有鱼儿吃钩就立马挥动鱼竿将鱼钓上来,否则就去干其他的事情;

模型解释:

        前三次调用recvfrom时没有数据可以返回,因此内核转而立即返回一个EWOULDBLOCK错误。第四次调用recvfrom时已经有一个数据报准备好了,它被复制到应用进程的缓冲区,于是recvfrom成功返回。进而开始处理数据。

        当一个应用进程像这样对一个非阻塞描述符循环调用recvfrom时,我们称之为轮询。应用进程持续轮询内核,以查看某个操作是否就绪。这样做往往耗费大量的CPU时间,不过像这样的模型偶尔也会遇到,通常是在专门提供某一种功能的系统中才有。

3. I/O复用(多路转接)

        有了I/O复用(多路转接),我们就可以调用select或poll或epoll,阻塞在这三个系统调用的某一个之上,而不是阻塞在真正的I/O系统调用上。

生活的例子:

        同样的还是钓鱼的例子,这次是王五钓鱼。王五钓鱼的方式与前两位有所不同。王五带来100个鱼竿来钓鱼,将鱼竿全部插在岸边,只要有一个鱼竿有鱼儿上够了,就立马钓上来;这样一来,整体的效率就上来了。

模型解释:

        我们阻塞于select调用,等待数据报套接字变为可读。当select返回套接字可读这一条件时,我们调用recvfrom把所读的数据报复制到应用进程缓冲区中。相比前两个,调用recvfrom就一定不会阻塞,前两个调用recvfrom是将等的时间和读取的时间一起做了,但是I/O复用就讲这两件事分开了。但是感觉I/O复用好像略显劣势,但是使用select最大的亮点就在于它可以等待多个描述符就绪。

4. 信号驱动式I/O

        我们也可以用信号,让内核在描述符就绪时发送SIGIO信号通知我们。我们称这种模型为信号驱动式I/O模型。

生活中的例子:

        赵六在这种方式下进行钓鱼(一根鱼竿),他将所有工作都做好后,在鱼竿上挂了个铃铛,如果铃铛响了就挥动鱼竿将鱼钓上来,否则就根本不管鱼竿。

模型解释:

        我们首先开启套接字的信号驱动功能,并通过sigaction系统调用安装一个信号处理函数。该系统调用将立即返回,我们的进程继续工作,也就是说它并没有被阻塞。当数据报准备好读取时,内核就为改进程产生一个SIGIO信号。我们随后既可以在信号处理函数中调用recvfrom函数读取数据报,并通知主循环数据报已经准备好待处理,也可以立即通知主循环,让他读取数据报。

        无论如何处理SIGIO信号,这种模型的优势在于等待数据报到达期间进程不被阻塞。主循环可以继续执行,只要等待来自信号处理函数的通知:既可以是数据报已准备好被处理,也可以是数据报已准备好被读取。(后续博客有相关程序案例)

5. 异步I/O

        异步I/O的工作机制:告知内核启动某个操作,并让内核在整个操作(包括将数据从内核复制到我们自己的缓冲区)完成后通知我们。这种模型与信号驱动I/O模型的主要区别在于:信号驱动式I/O是有内核通知我们何时可以启动一个I/O操作,而异步I/O模型是由内核通知我们I/O操作何时完成。

生活中的例子:

        没错还是钓鱼,这次是田七钓鱼。田七是一个有钱的老板,他给了自己的司机一个桶、一个电话、一个鱼竿,让司机去钓鱼,当鱼桶装满的时候再打电话告诉田七来拿鱼,而田七自己则开车去做其他事情去了。

模型解释:

        我们调用aio_read函数,给内核传递描述符、缓冲区指针、缓冲区大小和文件偏移,并告诉内核当整个操作完成时如何通知我们。该系统调用立即返回,而且在等待I/O完成期间,我们的进程不被阻塞。本例子中我们假设要求内核在操作完成时产生某个信号。该信号直到数据已复制到应用进程缓冲区才产生,这一点不同于信号驱动式I/O模型。(后续博客有相关程序案例,这里大致了解即可)

二、五种I/O模型的比较 

        如下图所示,前4种模型主要区别在于第一阶段,因为他们第二阶段都是一样的:在数据从内核复制到调用者的缓冲区期间,进程阻塞于recvfrom调用。相反,异步I/O模型在这两个阶段都要处理,从而不同于其他4种模型。

同步I/O和异步I/O的比较:

  • 同步I/O:导致请求进程阻塞,直到I/O操作完成;
  • 异步I/O:不导致请求进程阻塞;

简单的讲:就是是否参与了I/O操作;

        前四种I/O模型——阻塞式I/O模型、非阻塞式I/O模型、I/O复用(多路转接)和信号驱动式I/O模型都是同步I/O,因为其中真正的I/O操作(recvfrom)将进程阻塞。只有异步I/O模型是异步I/O。

三、I/O复用典型使用在下列网络应用场合

  • 当客户处理多个描述符时,必须使用I/O复用;
  • 如果一个TCP服务器既要处理监听套接字,又要处理已连接的套接字,一般就要使用I/O复用;
  • 如果一个服务器既要处理TCP,又要处理UDP,一般就要使用I/O复用。
  • 如果一个服务器要处理多个协议或多个服务,一般就需要使用I/O复用。 

http://www.ppmy.cn/news/4071.html

相关文章

【华为机试真题详解】开心消消乐【2022 Q4 | 100分】

文章目录 前言题目描述输入描述输出描述示例 1题目解析参考代码前言 《华为机试真题详解 Python实现》专栏含牛客网华为专栏、华为面经试题、华为OD机试真题。 如果您在准备华为的面试,期间有想了解的可以私信我,我会尽可能帮您解答,也可以给您一些建议! 本文解法非最优解…

HashMap(一)

HashMap集合简介 HashMap基于哈希表的Map接口实现,是以key-value存储形式存在,即主要用来存放键值对。HashMap 的实现不是同步的,这意味着它不是线程安全的。它的key、value都可以为null。此外,HashMap中的映射不是有序的。 JDK1…

【AIOT】QT样式QSS

使用桌面的PyQt或者web的flaskweb方便快捷的部署搭建可视化AI应用演示Demo,这里记录使用PyQt搭建基于Mediapipe和MixMLP网络的识别控制系统QSS样式代码。 Styles sheets are textual specifications that can be set on the whole application using QApplication::…

蓝桥杯:数字三角形

目录 题目描述 输入描述 输出描述 输入输出样例 输入 输出 思路: AC代码(Java): 题目描述 上图给出了一个数字三角形。从三角形的顶部到底部有很多条不同的路径。对于每条路径,把路径上面的数加起来可以得到一个…

1817. 查找用户活跃分钟数-快速排序

1817. 查找用户活跃分钟数-快速排序 给你用户在 LeetCode 的操作日志,和一个整数 k 。日志用一个二维整数数组 logs 表示,其中每个 logs[i] [IDi, timei] 表示 ID 为 IDi 的用户在 timei 分钟时执行了某个操作。 多个用户 可以同时执行操作&#xff0…

如何磁盘格式化?分享格式化U盘的3个方法

格式化可以有效管理硬盘,在一定程度上能保证磁盘的性能和使用寿命。尤其是我们遇到一些情况,必须要把U盘进行格式化才行。那么磁盘格式化怎么操作?遇到无法格式化的情况怎么办?别急,下面有3个关于格式化U盘的方法&…

【前端开发学习】4.JavaScript

文章目录1 JavaScript1.1 代码位置1.2 存在形式1.3 注释1.4 变量1.5 字符串类型案例:走马灯1.5 数组案例:动态数据1.6 对象(字典)案例:动态表格1.7 条件语句1.8 函数2 DOM2.1 事件绑定1 JavaScript 一门编程语言&…

五个月学完软件测试,现在分享以前自学的测试笔记

以前学习手抄的linux命令哈哈哈 定义 在规定的条件下对程序进行操作,以发现程序错误,衡量软件质量,并对其是否能满足设计要求进行评估的过程。 测试就是发现错误而执行程序的过程。 原则 保证测试的覆盖度,但是穷举测试是不可能…