你的程序为何卡顿?从LINUX I/O三大模式寻找答案

news/2025/10/16 21:29:09/文章来源:https://www.cnblogs.com/poemyang/p/19146666

你的程序为何卡顿?从LINUX I/O三大模式寻找答案

I/O交互流程
在LINUX中,内核空间和用户空间都位于虚拟内存中。LINUX采用两级保护机制:0级供内核使用,3级供用户程序使用。每个进程都有独立的用户空间(0~3G),对其他进程不可见,而最高的1G虚拟内核空间则由所有进程和内核共享。
操作系统和驱动程序运行在内核空间,应用程序运行在用户空间。由于LINUX使用虚拟内存机制,两者之间不能直接通过指针传递数据。用户空间必须通过系统调用请求内核协助完成I/O操作。内核会为每个I/O设备维护缓冲区,而用户空间的数据可能被换出,因此内核无法直接使用用户空间的指针。
对于一个输入操作,进程发起I/O系统调用后,内核会先检查缓冲区是否有缓存数据。如果没有,则从设备读取数据;如果有,则直接将数据复制到用户空间。因此,网络输入操作通常分为两个阶段:
1)内核空间阶段:内核通过协议栈和设备驱动程序接收数据,并将其存储在内核缓冲区;
2)用户空间阶段:数据从内核缓冲区复制到用户进程的缓冲区后,用户进程即可处理这些数据。

image

I/O操作方式
在操作系统中,通常有三种主要的I/O操作方式,每种方式都有其独特的特性和适用场景。

阻塞I/O
阻塞I/O(Blocking I/O)是最简单的I/O模型。当进程发起I/O操作(如read或write)时,当前线程会被阻塞,直到I/O操作完成。这种模型是标准的同步I/O实现,例如POSIX标准中的默认read和write系统调用。
阻塞I/O的优点是实现简单,适合低并发的场景,因为内核已经对这些系统调用进行了高度优化。然而,在并发场景下,阻塞I/O的性能瓶颈会显现出来:每个I/O操作都会阻塞一个线程,导致内核需要频繁地进行线程切换,这会增加上下文切换的开销,降低处理器缓存的利用率,并可能使依赖线程本地存储(Thread-Local Storage, TLS)的代码性能下降。

image

// 伪代码: 阻塞I/O
socket = accept(); // 阻塞,直到新连接到达
data = read(socket); // 阻塞,直到数据被读取
process(data);

非阻塞I/O
非阻塞I/O(Non-Blocking I/O)允许I/O操作在没有数据可用时立即返回,而不会阻塞执行线程。在非阻塞I/O模式下,如果数据未准备好,系统通常会返回一个错误码(如EAGAIN 或 EWOULDBLOCK),指示操作需要稍后重试。进程可以通过轮询监控多个文件描述符的就绪状态。
非阻塞I/O的优点是提高程序的并发性,因为它允许线程在等待I/O操作完成的同时,执行其他任务。然而,这种模式也带来了更高的编程复杂度,程序需要不断检查文件描述符的状态,以确保在数据可用时及时处理。这种轮询机制不仅增加了代码的复杂性,还可能导致处理器资源的浪费。

image

以下伪代码,展示了非阻塞I/O的执行过程。

// 伪代码: 非阻塞I/O
while (true) {data = read(socket);if (data != EAGAIN) {process(data);break;}// do other things...
}

异步 I/O
异步I/O (Asynchronous I/O)是一种真正的异步模型,进程在发起 I/O 操作后立即返回,并通过回调函数或事件通知机制在操作完成后得到通知。典型的实现包括Windows的OVERLAPPED和I/O完成端口(IOCP),以及LINUX的原生异步I/O(AIO)。需要注意的是,LINUX的原生AIO 仅对文件I/O有效,对网络I/O的支持有限。
异步I/O的优点是能够最大限度地提高并发性能,同时减少线程阻塞和上下文切换的开销。然而,异步I/O的实现和调试复杂度较高,且在某些平台上的支持不够完善。

image

// 伪代码: 异步I/O
// 定义一个I/O操作完成后的回调函数
void on_read_complete(data, error) {if (error) {handle_error(error);} else {process(data);}// 可以在回调中发起下一次异步读aio_read(socket, buffer, on_read_complete);
}// 1. 主程序发起异步读操作,并注册回调函数
// aio_read会立即返回,不会阻塞
aio_read(socket1, buffer1, on_read_complete);
aio_read(socket2, buffer2, on_read_complete);// 2. 主线程可以继续执行其他任务,或进入一个等待退出的循环
do_other_work();
event_loop_wait_for_shutdown(); // 例如,等待信号

未完待续

很高兴与你相遇!如果你喜欢本文内容,记得关注哦

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

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

相关文章

日总结 13

BP 神经网络(Back Propagation Neural Network)是一种基于误差反向传播算法训练的多层前馈神经网络,核心是通过反向传播误差来调整网络权重,从而实现对复杂非线性关系的学习与拟合,是深度学习的基础模型之一。 一…

开源许可协议 gpl vs mit?

大一点的项目用GPL,与社区个人共享劳动过程与成果,保护劳动果实不被商业公司吸血、完全抄袭与窃取。 小项目或者纯依赖库,用MIT,方便你我他接手,续上代码更新。

二进制警报器

二进制警报器 在线解决以下问题:给定长度为 \(n\) 的数组,\(q\) 次操作:单点加(或多点加,视为多次单点加)设置警报器 \((S,v)\),当集合 \(S\) 对应位置的和达到 \(v\) 时报警。为了区分,我们将原问题中的报警称…

题解:P8019 [ONTAK2015] OR-XOR

思路 题目要求我们把序列分成 \(m\) 段,使得每段区间的异或和的结果按位或后的结果尽可能地小。那么就有一个显然的贪心,从高到低枚举二进制位,尽可能划分使高位按位或后为 \(0\) 的区间,这么做得到的答案是最优的…

DP 思维好题(转载)

转载自 https://www.luogu.com.cn/discuss/1174071 P3881, P3170, P3179, P3190, P3272, P3290, P3336, P3351, P3600, P3724, P5075, P1721, P1924, P1933, P2145, P3685, P2304, P2289, P2612, P2703, P4365, P4383,…

常见问题处理 --- win卡任务栏 设置无法打开 桌面重启

常见问题处理 --- win卡任务栏 设置无法打开 桌面重启解决方法 下载autoruns在微软官网 https://learn.microsoft.com/en-us/sysinternals/downloads/ 打开后找到explore 取消所有黄色的勾选 如果无法操作切换账户即可…

python sse的是什么?

python sse1.sse是什么?是一个通信协议。最主要的是, 服务器必须发送一个 Content-Type 为 text/event-stream 的响应头,这告诉客户端:“接下来我发送的不是普通的 HTML 或 JSON,而是一个事件流。” ============…

万字长文详述单据引擎原理、流程、单据管理 - 智慧园区

本文将为你深入剖析单据引擎的原理、架构、设计以及管理方法,帮助你构建一个高效、灵活且可靠的单据处理系统。 前言 单据引擎是做什么的?为什么要了解单据引擎? B端产品,一不小心就会变成项目,一个个定制交付,…

windows 链接共享打印机出现错误0x00000709?打印机0x0000011b错误?0x0000bcd、0x00000709、0x00000011b

安装 点击这里获取:所有修复工具都放这里了 ​​ 图片 第一款:全能打印机问题修复工具 ​​功能都在图片上面了,如果还需要安装其它支持的程序,会自动提示安装第二款:打印机共享维护工具等4个文件 WIN10 2H22和WI…

解码Linux文件IO目录检索与文件属性

目录检索的核心需求 当需要批量访问某个路径下的多个文件时,手动调用open函数逐个处理效率极低。Linux 系统将目录视为特殊文件,提供了一套专门的目录操作接口,可高效实现目录的创建、删除、打开、读取,以及文件属…

p66实验题

""" CIFAR-10 图像分类简化版(使用 sklearn) 在安装 TensorFlow 之前可以先运行这个版本 """ import numpy as np import matplotlib.pyplot as plt from sklearn.datasets import fe…

20251016

10.16今天体育课体测,让我发现自己BMI指数居然是25.7,这令我非常不能接受。因此,我要开始为期两个半月的减脂,控制自己,打造健康强壮身体,于是我今天下午直接到操场跑步3公里,我感觉我现在状况非常好。未来我会…

C# - 串口助手

串口通信工具准备 (1)sscom5.13.1.exe: 串口调试工具 (2)VSPD: 是一种虚拟串口驱动程序,用于模拟和创建多个虚拟串口,以便在计算机间进行串口通信 VSPD 串口介绍Sent: 0 Bytes表示从该串口发送出去的数据字节数为…

虚拟线程的pinned问题终于被jdk25完美解决了

虚拟线程是一个非常有用的特征,但是JDK25以前,一直存在pinned问题,一些场景下会导致平台线程被占用无法释放。 比如下面的代码,在JDK 21下运行时,会卡住:import java.time.Duration; import java.util.concurren…

077_尚硅谷_单分支基本使用

077_尚硅谷_单分支基本使用1.单分支基本介绍2.例题判断是否18岁

【比赛记录】2025NOIP 冲刺模拟赛合集I

2025CSP-S模拟赛64A B C D Sum Rank50 0 0 - 50 7/7挂 155pts,挂挂挂挂挂挂挂挂挂挂挂挂挂挂挂挂挂挂挂挂挂挂挂挂挂挂挂挂挂挂挂挂挂挂挂挂挂挂挂挂挂挂挂挂挂挂挂挂挂挂挂挂挂挂挂挂挂挂挂挂挂挂挂挂挂挂挂挂挂挂挂…

12 继承--instanceof和类型转换

12 继承--instanceof和类型转换多态 父类的引用指向子类的类型 Father f = new Son(); 而能执行的方法只看左边的类型. 父类可以指向子类,但不能调用子类独有的方法 如果非要调用,可以进行强制类型转换.注意事项:多态是…

C0214 拔树游戏 题解

C0214 拔树游戏 题解C0214 拔树游戏 题解 这道题挺有趣的。 不难发现每一次的拔树操作就是对一个根节点的所有子节点(只是下一层)取最小点权的那个节点取代本身。同时发现,因为每次取的节点都是最小的,所以在堆…