Linux - 五种常见I/O模型
I/O操作 (输入/输出操作, Input/Output) 是指计算机与外部设备就行数据交互的过程.
什么是外部设备: 如键盘, 鼠标, 硬盘, 网卡等.
五种常见的 I/O 模型:
- 阻塞 I/O
- 非阻塞 I/O
- 信号驱动 I/O
- I/O 多路复用
- 异步 I/O
阻塞 I/O
阻塞 I/O 的特点: 当用户发起 I/O 请求后, 进程/线程就会被阻塞, 直到这个 I/O 操作完成.
1. 发起 I/O 请求 ( read/write ).
2. 如果数据为准备好, 那么进程/线程就会被阻塞, 进入等待状态
3. 数据准备好了, 操作系统将数据复制到用户空间, 进程/线程获取到了数据, 就被唤醒继续执行
就像是一个人去钓鱼, 当他甩鱼竿之后, 就一直盯着鱼竿什么都不做, 直到看见有鱼上钩了, 将鱼竿收起来.
阻塞 I/O: 实现简单, 容易理解.
缺点: 但是效率低下, 因为进程/线程会一直等待 I/O 操作完成, 等待期间不会执行其他的任务, 资源的利用率低.
非阻塞 I/O
上面了解了阻塞 I/O 是一直等待 I/O 操作完成形成阻塞.
那么非阻塞 I/O 也就是当进程/线程发起 I/O 请求后, 即使数据没有准备好, 也会立即返回. 不会被阻塞住.
1. 进程/线程发起非阻塞 I/O
2. 如果数据未准备好, 操作系统就会返回一个错误
3. 进程或线程需要不断的轮询, 检查数据是否准备好
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>#define BUFFER_SIZE 1024int main() {char buffer[BUFFER_SIZE];int flags;// 获取标准输入的文件描述符的当前标志flags = fcntl(STDIN_FILENO, F_GETFL, 0);if (flags == -1) {perror("fcntl F_GETFL");return 1;}// 设置标准输入为非阻塞模式if (fcntl(STDIN_FILENO, F_SETFL, flags | O_NONBLOCK) == -1) {perror("fcntl F_SETFL");return 1;}while (1) {// 尝试从标准输入读取数据ssize_t n = read(STDIN_FILENO, buffer, BUFFER_SIZE - 1);if (n == -1) {if (errno == EAGAIN || errno == EWOULDBLOCK) {// 没有数据可读,进行其他操作printf("No input available, doing other work...\n");sleep(1);} else {perror("read");break;}} else if (n > 0) {// 读取到数据,处理数据buffer[n] = '\0';printf("Read input: %s", buffer);} else {break;} }return 0;
}
可以看到代码中对于 read 函数的操作需要使用循环不断的检查数据是否准备完成. 这个不断循环的过程就称为轮询.
就像去钓鱼, 我不会一直在那盯着鱼竿, 而是每过一会就去看看有没有鱼上钩, 在这期间可以去看看手机, 刷刷视频.
优点: 如果检测到数据还没准备好, 那么此时程序也可以执行一些耗时不长的任务, 这也是非阻塞 I/O 的一个优点.
缺点: 轮询机制会占用大量的 CPU 资源, 效率低下.
信号驱动 I/O
基于信号通知进程/线程 I/O 操作完成.
1. 程序注册一个信号处理器
2. 当数据准备好了, 操作系统就会发送对应的信号通知程序
3. 程序接收到信号后, 信号处理器就会执行对应操作
钓鱼的时候, 每过一段时间就去看看太麻烦了, 所以在鱼竿上装了一个铃铛, 当有鱼咬钩时, 铃铛就会响. 铃铛响将相当于是信号. 铃铛不响我就继续做我自己的事, 看看手机....
优点: 这也是非阻塞的一个 I/O 模型, 有着非阻塞 I/O 的优点. 通过信号可以准确快速的响应 I/O 事件.
缺点: 那么引入了信号, 程序就必然会变得更加复杂, 容易出现错误.
I/O 多路复用
上面的 I/O 模型中, 都是对某一个 I/O 操作进行管理.
I/O 多路复用则是对于多个 I/O 操作进行管理, 当某个 文件描述符(fd) 准备好了后, 系统就会发送通知, 此时程序就可以对这些 准备好了的 fd 进行操作
1. 通过 select, poll 或 epoll 监控多个文件描述符 (fd) 的状态
2. 当有 fd 准备好了后, 操作系统通知程序, 程序就对这些准备好的 fd 进行操作
上面钓鱼中, 我只带了一根钓鱼竿 , 那么现在我带了50根钓鱼竿, 50根杆同时钓鱼, 效率大幅提升.
异步 I/O
前面的四种都是同步 I/O. I/O = 等待 + 拷贝. 同步 I/O 至少参与了一个过程 (等待或拷贝).
而异步 I/O 则是两个都不参加. 有操作系统完成 I/O 操作, 操作系统完成后通知进程/线程. 进程/线程可以通过回调函数或事件通知机制获取本次 I/O 操作的结果.
1. 用户进程/线程发起异步 I/O 请求, 直接返回
2. 操作系统负责完成 I/O 操作, 并在完成后通知用户进程/线程
3. 用户线程通过回调函数或事件通知机制获取本次 I/O 结果
之前钓鱼, 都是自己在操作, 但是现在我雇佣一个人来帮我钓鱼, 当他钓鱼结束后, 将钓到的鱼交给我就行, 我不用去管钓鱼的事.
当然这一种模型也很复杂的. 对于程序员的要求较高
同步和异步
同步: 必须等待任务完成后, 才能执行下一个任务. 像上面的四种 I/O 模型中, 无论是阻塞还是非阻塞, 我们都在等待它的返回值 (等待它执行的结果). 只有等到了它执行的结果, 程序才会继续向下执行. 异步也是不断地继续轮询, 直到等到执行的结果
异步: 则不会等待这个任务, 而是继续向后执行. 如异步的进行 I/O 请求, 虽然也会直接进行返回, 但是这个返回并没有附带本次操作的结果. 重点并不是返回, 重点是本次请求的结果是否被等待了. 至于本次任务执行的结果, 则是通过其他方法通知给程序 (如: 回调函数等)
相关文章:
Linux - 五种常见I/O模型
I/O操作 (输入/输出操作, Input/Output) 是指计算机与外部设备就行数据交互的过程. 什么是外部设备: 如键盘, 鼠标, 硬盘, 网卡等. 五种常见的 I/O 模型: 阻塞 I/O非阻塞 I/O信号驱动 I/OI/O 多路复用异步 I/O 阻塞 I/O 阻塞 I/O 的特点: 当用户发起 I/O 请求后, 进程/线程就…...

【负载均衡式在线OJ】加载题目信息(文件版)
目录 如何读取文件 -- 常见流程 代码 如何读取文件 -- 常见流程 在C中使用 std::ifstream来打开文件流是一个常见的操作,用于创建一个输入文件流,并尝试打开名为 question_list的文件。if (!in.is_open()):检查文件是否成功打开。如果文件未…...
“上门按摩” 小程序开发项目:基于 SOP 的全流程管理
在竞争激烈的生活服务市场,“上门按摩” 服务需求日益增长。为满足这一需求,我们启动了 O2O 模式的 “上门按摩” 小程序开发项目,该项目涵盖客户端、系统管理端、技师端。以下将通过各类 SOP 对项目进行全面管理,确保项目顺利推进。 一、项目启动 SOP:5W2H 分析法 What(…...

WPF1-从最简单的xaml开始
1. 最简单的WPF应用 1.1. App.config1.2. App.xaml 和 App.xaml.cs1.3. MainWindow.xaml 和 MainWindow.xaml.cs 2. 正式开始分析 2.1. 声明即定义2.2. 命名空间 2.2.1. xaml的Property和Attribute2.2.2. xaml中命名空间2.2.3. partial关键字 学习WPF,肯定要先学…...

2025牛客寒假算法营2
A题 知识点:模拟 打卡。检查给定的七个整数是否仅包含 1,2,3,5,6 即可。为了便于书写,我们可以反过来,检查这七个整数是否不为 4 和 7。 时间 O(1);空间 O(1)。 #include <bits/stdc.h> using namespace std;signed main()…...

编译Android平台使用的FFmpeg库
目录 前言 一、编译环境 二、搭建环境 1.安装MSYS2 2.更新系统包 2.1 打开MSYS2 MinGW 64-bit终端(mingw64.exe) 2.2 更新所有软件包到最新版本 2.3 安装必要的工具和库。 3. 克隆FFmpeg源码 4. 配置编译选项 5. 执行编译 总结 前言 记录学习…...

【C++高并发服务器WebServer】-2:exec函数簇、进程控制
本文目录 一、exec函数簇介绍二、exec函数簇 一、exec函数簇介绍 exec 函数族的作用是根据指定的文件名找到可执行文件,并用它来取代调用进程的内容,换句话说,就是在调用进程内部执行一个可执行文件。 exec函数族的函数执行成功后不会返回&…...

力扣707题(2)——设计链表
#题目 #3,5和6的代码 今天看剩下几个题的代码,1,2,4的代码已经在上篇博客写过了想看的小伙伴移步到: 力扣707题——设计链表-CSDN博客 //第3题头插法 void addAtHead(int val){ //记录头结点ListNode nhead; //新节点的创建,并让它指向原本头结点的后…...

K8S中ingress详解
Ingress介绍 Kubernetes 集群中,服务(Service)是一种抽象,它定义了一种访问 Pod 的方式,无论这些 Pod 如何变化,服务都保持不变。服务可以被映射到一个静态的 IP 地址(ClusterIP)、一…...

SpringBoot打包为JAR包或WAR 包,这两种打包方式在运行时端口将如何采用?又有什么不同?这篇文章将给你解惑
你们好,我是金金金。 前提 SpringBoot打包方式:不是jar就是war包 场景 写这篇文章也是我遇到一个很不理解的点,所以就去研究了一下 场景如下: 这是后端生产配置文件给项目设置的端口,然后我前端写的url是:我就很纳闷,前端写了域名以及后端服务上下文路径,咋没写端口呢,…...

zabbix6.0安装及常用监控配置
文章目录 部署zabbix-serverzabbix监控节点部署解决zabbix中文乱码创建主机组创建模版配置主机与模版关联 监控boot分区监控网卡流量出网卡流量监控进入和出的总流量监控内存监控服务器端口用户自定应监控key值 (监控mysql查询数量)zabbix触发器监控cpu监控入网卡流量 邮件告警…...

SQL-leetcode—1179. 重新格式化部门表
1179. 重新格式化部门表 表 Department: ---------------------- | Column Name | Type | ---------------------- | id | int | | revenue | int | | month | varchar | ---------------------- 在 SQL 中,(id, month) 是表的联合主键。 这个表格有关…...

JavaWeb 学习笔记 XML 和 Json 篇 | 020
今日推荐语 愿你遇见好天气,愿你的征途铺满了星星——圣埃克苏佩里 日期 学习内容 打卡编号2025年01月23日JavaWeb笔记 XML 和 Json 篇020 前言 哈喽,我是菜鸟阿康。 以下是我的学习笔记,既做打卡也做分享,希望对你也有所帮助…...
在Raspbian上,如何获取树莓派的CPU当前频率
本文不用汇编实现,因为我是要用在 Go 里的,Go 并不支持内联汇编,要用汇编比较麻烦。而且项目并不是很在意性能,所以直接用命令获取内核准备好的。 在Raspbian上,CPU 信息存放在/sys/devices/system/cpu/中,…...
网络打印机的搜索与连接(一)
介绍 网络打印机就是可以通过网络连接上的打印机,这类打印机分2种:自身具有互联网接入功能可以分配IP的打印机我们称为网络打印机、另外一种就是被某台电脑连接上去后通过共享的方式共享到网络里面的我们称为共享打印机。现在还有一种可以通过互联网连接…...

LangChain + llamaFactory + Qwen2-7b-VL 构建本地RAG问答系统
单纯仅靠LLM会产生误导性的 “幻觉”,训练数据会过时,处理特定知识时效率不高,缺乏专业领域的深度洞察,同时在推理能力上也有所欠缺。 正是在这样的背景下,检索增强生成技术(Retrieval-Augmented Generati…...

【自然语言处理(NLP)】介绍、发展史
文章目录 介绍发展史1. 规则驱动时期(20世纪50年代-80年代)技术特点标志性成果 2. 统计方法兴起(1990年代-2000年代)技术特点标志性成果 3. 神经网络复兴(2010年代初至今)技术特点标志性成果 4. 集成与应用…...

1.CSS的三大特性
css有三个非常重要的三个特性:层叠性、继承性、优先级 1.1 层叠性 想通选择器给设置想听的样式,此时一个样式就会覆盖(层叠)另一个冲突的样式。层叠性主要是解决样式冲突的问题。 <!DOCTYPE html> <html lang"en&…...

【分布式日志篇】从工具选型到实战部署:全面解析日志采集与管理路径
网罗开发 (小红书、快手、视频号同名) 大家好,我是 展菲,目前在上市企业从事人工智能项目研发管理工作,平时热衷于分享各种编程领域的软硬技能知识以及前沿技术,包括iOS、前端、Harmony OS、Java、Python等…...

基于springcloud汽车信息分析与可视化系统
基于Spring Cloud的汽车信息分析与可视化系统是一款旨在整合、分析汽车相关数据并以直观可视化方式呈现的应用系统。 一、系统架构 该系统基于先进的Spring Cloud架构构建,充分利用其分布式、微服务特性,确保系统具备高可用性、可扩展性和灵活性。Spri…...

(LeetCode 每日一题) 3442. 奇偶频次间的最大差值 I (哈希、字符串)
题目:3442. 奇偶频次间的最大差值 I 思路 :哈希,时间复杂度0(n)。 用哈希表来记录每个字符串中字符的分布情况,哈希表这里用数组即可实现。 C版本: class Solution { public:int maxDifference(string s) {int a[26]…...

接口测试中缓存处理策略
在接口测试中,缓存处理策略是一个关键环节,直接影响测试结果的准确性和可靠性。合理的缓存处理策略能够确保测试环境的一致性,避免因缓存数据导致的测试偏差。以下是接口测试中常见的缓存处理策略及其详细说明: 一、缓存处理的核…...
day52 ResNet18 CBAM
在深度学习的旅程中,我们不断探索如何提升模型的性能。今天,我将分享我在 ResNet18 模型中插入 CBAM(Convolutional Block Attention Module)模块,并采用分阶段微调策略的实践过程。通过这个过程,我不仅提升…...

JavaScript 中的 ES|QL:利用 Apache Arrow 工具
作者:来自 Elastic Jeffrey Rengifo 学习如何将 ES|QL 与 JavaScript 的 Apache Arrow 客户端工具一起使用。 想获得 Elastic 认证吗?了解下一期 Elasticsearch Engineer 培训的时间吧! Elasticsearch 拥有众多新功能,助你为自己…...
解锁数据库简洁之道:FastAPI与SQLModel实战指南
在构建现代Web应用程序时,与数据库的交互无疑是核心环节。虽然传统的数据库操作方式(如直接编写SQL语句与psycopg2交互)赋予了我们精细的控制权,但在面对日益复杂的业务逻辑和快速迭代的需求时,这种方式的开发效率和可…...

ESP32读取DHT11温湿度数据
芯片:ESP32 环境:Arduino 一、安装DHT11传感器库 红框的库,别安装错了 二、代码 注意,DATA口要连接在D15上 #include "DHT.h" // 包含DHT库#define DHTPIN 15 // 定义DHT11数据引脚连接到ESP32的GPIO15 #define D…...
Java 加密常用的各种算法及其选择
在数字化时代,数据安全至关重要,Java 作为广泛应用的编程语言,提供了丰富的加密算法来保障数据的保密性、完整性和真实性。了解这些常用加密算法及其适用场景,有助于开发者在不同的业务需求中做出正确的选择。 一、对称加密算法…...
TRS收益互换:跨境资本流动的金融创新工具与系统化解决方案
一、TRS收益互换的本质与业务逻辑 (一)概念解析 TRS(Total Return Swap)收益互换是一种金融衍生工具,指交易双方约定在未来一定期限内,基于特定资产或指数的表现进行现金流交换的协议。其核心特征包括&am…...

力扣热题100 k个一组反转链表题解
题目: 代码: func reverseKGroup(head *ListNode, k int) *ListNode {cur : headfor i : 0; i < k; i {if cur nil {return head}cur cur.Next}newHead : reverse(head, cur)head.Next reverseKGroup(cur, k)return newHead }func reverse(start, end *ListNode) *ListN…...
Caliper 配置文件解析:fisco-bcos.json
config.yaml 文件 config.yaml 是 Caliper 的主配置文件,通常包含以下内容: test:name: fisco-bcos-test # 测试名称description: Performance test of FISCO-BCOS # 测试描述workers:type: local # 工作进程类型number: 5 # 工作进程数量monitor:type: - docker- pro…...