初识Linux · 五种IO模型和非阻塞IO

目录

前言:

五种IO模型

什么是IO

IO模型

非阻塞IO


前言:

前文我们已经将网络的基本原理介绍完了,都是通过围绕TCP/IP四层协议,将应用层,传输层,网络层,数据链路层全部介绍完毕,至于部分小主题,比如ARP欺骗,HTTP协议的原理,cookie以及session等内容,我们放在后面介绍。

本文以及之后的内容,主要通过是介绍IO相关的问题,通过IO模型的介绍,从而引出多路复用的具体内容,通过介绍select,poll,epoll,最后再单独介绍一下Reactor,网络的基本原理我们就介绍完了。

那么废话不多说,我们直接进入五种IO模型。


五种IO模型

什么是IO

对于IO这个话题,我们从语言阶段,一直到了现在都经常谈论,因为IO问题不管在哪个阶段都是非常重要的,从C语言阶段的printf scanf,到文件操作的read和write涉及到了IO,即便是Linux,我们从一开始的文件系统,引出了文件描述符,到后面的网络也是一直使用文件描述符的概念,足以看出IO在编程中的重要性了。

那么问题来了,一开始我们只是粗略的将IO认定为是输入输出,今天我们进一步探讨,当我们第一次使用scanf的时候,我们发现只要我们不输入,系统就会阻塞住,系统在干什么呢?

系统在等我们输入,所以IO有一个非常重要的过程是:等待。当我们输入数据之后,系统也收到了数据也就不再等待,就执行了下一步操作了。这个过程还有读取的操作,或者是写入的操作,但是不管怎么说,都是从发送缓冲区/接收缓冲区拷贝数据到应用层的缓冲区。

所以实际上的IO = 等待 + 拷贝

而我们从一开始的学习到现在,使用到的基本上都是阻塞IO,自然也就存在非阻塞的IO,我们放在IO模型里面介绍。那么我们在MySQL中介绍索引的时候,我们提及到了IO次数如果多了,就一定会降低效率,所以我们就要使用高效的IO,那么高效的IO实际上减少了等待操作在IO中的比例

IO模型

对于IO模型我们拿钓鱼举例子,假设有五个人,分别在鱼塘中钓鱼,张三拿个鱼竿就坐在那里一直等待,当别人问他什么事,他也不理睬,这是第一种IO模型;李四拿个鱼竿放在那里,就不管了,转身去做自己的事儿了,然后定期来查看鱼竿的情况,这是第二种IO模型;王五拿个鱼竿,钓鱼的时候放个铃铛,当鱼上钩了,就放在自己手里的事儿,然后钓鱼,这是第三种IO模型;赵六就很有说法了,拿了一卡车的鱼竿过来了,同时使用很多的鱼竿,然后一个一个的检查鱼竿情况,这是第四种IO模型;田七的钓鱼操作是派遣一个人,让这个人像张三一样,完成钓鱼的等待和钓操作,自己就转身去干其他事儿了,也就是田七只负责吃的操作,这是第五种IO模型。

那么上述都是一个口语化的介绍,实际上的名称叫做:
第一种,阻塞IO,比如我们常见的read recvfrom scanf都是阻塞IO的代表,如果系统的数据还没有准备好,强行非阻塞的话就会返回错误码11,一会儿我们可以实验。

第二种,非阻塞IO,非阻塞IO顾名思义,IO的同时干自己的事儿,那么这意味着需要反反复复的尝试读写文件描述符,这个过程称为轮询,但是因为会反反复复的操作文件操作符,所以会对CPU资源造成较大的浪费,一般根据特定情况使用:

第三种,信号驱动IO,同王五一样,铃铛就像信号,内核将数据处理好之后,就使用信号SIGIO通知应用程序,这种IO模型实际上也是非阻塞IO模型:

第四种,IO多路转接,它实际上是阻塞IO的plus版本,也就是说张三一个人进行阻塞IO的时候,赵六已经创建了100个张三的分身了,所以实际上的流程图也就是IO的流程图,那么多路转接也是我们后面的主题,介绍select poll epoll就是从这里引出的:

第五种,异步IO,异步IO实际上就是先让内核吧数据报准备好,再进行拷贝的,最后OS给应用程序发信号通知准备好了,这个过程田七只是作为发起IO,但是等的过程交给了内核,然后他再来负责拷贝,那么被称为异步IO就是因为发出 I/O 请求的线程不会阻塞等待,后续的 I/O 完成由内核负责异步处理,应用程序通过信号、回调或轮询某种状态(如 aio_error())来获取 I/O 是否完成,所以它是异步的。

那么以上五种IO中,第四种IO多路复用的效率是最高的,因为大大减少了等待了时间,这也是之后我们为什么围绕它展开的理由。


非阻塞IO

对于阻塞IO来说,是我们最常见,也是最经常使用的IO模型,但是如果我们今天想尝试一下非阻塞IO怎么办呢?我们可以使用函数fcntl

第一个参数是对应的文件描述符,第二个参数是执行的控制命令,第三个参数取决于第三个参数,可以忽略。

一般常用的cmd有F_SETFL,F_GETFL,GET用来获取状态标志,SET用来获取标志,比如我们想要将一个文件描述符设置为非阻塞的就可以这样操作:

void SetNoBlock()
{int n = ::fcntl(0, F_GETFL);if(n < 0)std::cout << "Error" << std::endl;else   fcntl(0, F_SETFL, n | O_NONBLOCK);
}int main() 
{SetNoBlock();while(true){char buffer[1024];ssize_t n = ::read(0, buffer, sizeof(buffer));if(n > 0){std::string str = buffer;std::cout << str << std::endl;}else if(n == 0){std::cout << "read done!" << std::endl;break;}else{// errno == 11 EWOULDBLOCK EAGAINif(errno == EWOULDBLOCK){continue;}std::cout << "GG" << std::endl;sleep(1);}}return 0;
}

我们会发现如果我们强行让read这种阻塞IO变成非阻塞IO,就会导致返回的值是负数,所以这个时候就有这种情况:发生错误是因为read本身出错还是因为非阻塞下没有数据可读导致read不会阻塞直接返回-1?所以我们可使用EWOULDBLOCK比较一下,当然了,它的本质是11,也是EAGAIN:

那么IO模型先到这里,算是一个开胃小菜~


感谢阅读!

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Node.js 24发布:性能与安全双提升

在科技的迅速发展中&#xff0c;Node.js作为一个备受青睐的开源跨平台Java运行环境&#xff0c;近日迎来了其24.0版本的正式发布。此次更新不仅承诺提升性能和安全性&#xff0c;还为开发者提供了更为顺畅的开发体验&#xff0c;值得我们深入探讨。 Node.js 24.0的最大亮点之一…

SLAM文献之-SuperOdometry: Lightweight LiDAR-inertial Odometry and Mapping

《Super Odometry: IMU-centric LiDAR-Visual-Inertial Estimator for Challenging Environments》是一篇旨在增强 SLAM 系统在恶劣环境下鲁棒性的工作&#xff0c;尤其关注尘雾、烟雾等遮挡条件下的鲁棒估计。下面从算法原理、公式推导、创新点和应用场景四个方面进行详细解析…

指令烧录ORIN NANO操作系统

1 概述 模组为ORIN NANO 4GB版本 Ubuntu系统为18.04虚拟机 说明&#xff1a;刷机过程会有重新连接USB的操作&#xff0c;烧写过程需要注意虚拟机提示&#xff0c;官方不建议使用虚拟机&#xff0c;建议直接使用ubuntu操作系统的机器。 2 下载烧录所需文件 进入到下载网址&am…

游戏引擎学习第287天:加入brain逻辑

Blackboard&#xff1a;动态控制类似蛇的多节实体 我们目前正在处理一个关于实体系统如何以组合方式进行管理的问题。具体来说&#xff0c;是在游戏中实现多个实体可以共同或独立行动的机制。例如&#xff0c;我们的主角拥有两个实体组成部分&#xff0c;一个是身体&#xff0…

QML定时器Timer和线程任务WorkerScript

定时器 Timer 属性 interval: 事件间隔毫秒repeat: 多次执行&#xff0c;默认只执行一次running: 定时器启动triggeredOnStart: 定时器启动时立刻触发一次事件 信号 triggered(): 定时时间到&#xff0c;触发此信号 方法 restart(): 重启定时器start(): 启动定时器stop(): 停止…

Linux中的域名解析服务器

一、DNS&#xff08;域名系统&#xff09;详解 1. 核心功能与特点 特性说明核心作用将域名&#xff08;如 www.example.com&#xff09;转换为 IP 地址&#xff08;如 192.168.1.1&#xff09;&#xff0c;实现人类可读地址与机器可读地址的映射。端口与协议- 默认端口&#…

Springboot2

1、搭建环境 2、配置文件 application.properties application.yml 3、springboot接收请求 springspringmvc 接收请求 响应数据 4、springboot集成jdbc spring-boot-starter-jdbc.jar JdbcTemplate(update|query) 5、springboot自动装配原理&#xff08;重点&#x…

【课堂笔记】核方法和Mercer定理

文章目录 Kernal引入定义Mercer定理描述有限情形证明一般情形证明 Kernal 引入 在实际数据中常常遇到不可线性分割的情况&#xff0c;此时通常需要将其映射到高维空间中&#xff0c;使其变得线性可分。例如二维数据&#xff1a; 通过映射 ϕ ( x 1 , x 2 ) ( x 1 2 , 2 x 1…

谈谈未来iOS越狱或巨魔是否会消失

2024年10月的预测&#xff0c;先说结论&#xff1a; 巨魔iOS17.1消失概率为99%。 因为巨魔强依赖的漏洞就是一个签名漏洞&#xff0c;攻击面有限又经过2轮修复&#xff0c;第3次出现漏洞的概率极低。而越狱的话由于系统组件和服务较多&#xff0c;所以出现漏洞概率高攻击面多&…

根据当前日期计算并选取上一个月和上一个季度的日期范围,用于日期控件的快捷选取功能

1.选择月份范围 代码如下&#xff1a; <el-date-picker v-model"value" type"monthrange" align"right" unlink-panels range-separator"至"start-placeholder"开始月份" end-placeholder"结束月份" :picker-…

用户栈的高效解析逻辑

一、背景 在之前的博客 内核逻辑里抓取用户栈的几种方法-CSDN博客 里&#xff0c;介绍了使用内核逻辑进行用户栈的函数地址的抓取逻辑&#xff0c;但是并没有涉及如何解析出函数符号的逻辑。 就如perf工具一样&#xff0c;它也是分为两个步骤&#xff0c;一个步骤是内核态抓取…

vue3 el-table 行号

在 Vue 3 中&#xff0c;使用 Element Plus 的 <el-table> 组件来创建表格时&#xff0c;如果你想添加行号&#xff08;即每一行的编号&#xff09;&#xff0c;可以通过自定义列来实现。下面是如何实现的步骤&#xff1a; 1. 安装 Element Plus 首先&#xff0c;确保你…

Linux:进程信号---信号的保存与处理

文章目录 1. 信号的保存1.1 信号的状态管理 2. 信号的处理2.1 用户态与内核态2.2 信号处理和捕捉的内核原理2.3 sigaction函数 3. 可重入函数4. Volatile5. SIGCHLD信号 序&#xff1a;在上一章中&#xff0c;我们对信号的概念及其识别的底层原理有了一定认识&#xff0c;也知道…

UML 图的细分类别及其应用

统一建模语言&#xff08;UML&#xff0c;Unified Modeling Language&#xff09;是一种用于软件系统建模的标准化语言&#xff0c;广泛应用于软件工程领域。UML 图分为多种类别&#xff0c;每种图都有其特定的用途和特点。本文将详细介绍 UML 图的细分类别&#xff0c;包括 类…

「极简」扣子(coze)教程 | 小程序UI设计进阶!控件可见性设置

大师兄在上一期的内容中对用户的UI做了一些简单的介绍。这期大师兄继续介绍UI设计上的进阶小技巧&#xff0c;帮我们获得更好的使用体验。 扣子&#xff08;coze&#xff09;编程 「极简」扣子(coze)教程 | 3分钟学会小程序UI设计&#xff01;从零开始创建页面和瓷片按钮 「极…

2025年渗透测试面试题总结-快手[实习]安全工程师(题目+回答)

网络安全领域各种资源&#xff0c;学习文档&#xff0c;以及工具分享、前沿信息分享、POC、EXP分享。不定期分享各种好玩的项目及好用的工具&#xff0c;欢迎关注。 目录 快手[实习]安全工程师 一面问题分析与详细回答 1. 自我介绍 4. 项目问题与解决 7. 防止SQL注入&…

WordPress Madara插件存在文件包含漏洞(CVE-2025-4524)

免责声明 本文档所述漏洞详情及复现方法仅限用于合法授权的安全研究和学术教育用途。任何个人或组织不得利用本文内容从事未经许可的渗透测试、网络攻击或其他违法行为。使用者应确保其行为符合相关法律法规,并取得目标系统的明确授权。 对于因不当使用本文信息而造成的任何直…

互联网大厂Java面试场景:从Spring Boot到分布式缓存技术的探讨

互联网大厂Java面试场景&#xff1a;从Spring Boot到分布式缓存技术的探讨 场景描述 互联网大厂某次Java开发岗面试&#xff0c;主考官是一位严肃的技术专家&#xff0c;而应聘者则是搞笑的程序员“码农明哥”。面试围绕音视频场景的技术解决方案展开&#xff0c;探讨从Sprin…

leetcode hot100刷题日记——8.合并区间

class Solution { public:vector<vector<int>> merge(vector<vector<int>>& intervals) {if(intervals.empty()){//复习empty函数啊&#xff0c;日记1有的return {};}// 按照区间的起始位置进行排序sort(intervals.begin(), intervals.end());vect…

Unity中GPU Instancing使用整理

GPU Instancing是一种绘制调用优化方法,可在单个绘制调用中渲染具有相同材质Mesh的多个副本(实例),可用于绘制在场景中多次出现的几何体(例如,树木或灌木丛),在同一绘制调用中渲染相同的网格,每个实例可以具有不同的属性(如 Color 或 Scale),渲染多个实例的绘制调用…