文章目录

  • 一、IO为什么慢?
  • 一、阻塞IO
  • 二、非阻塞IO
  • 三、信号驱动IO
  • 四、IO多路复用
  • 五、异步IO

一、IO为什么慢?

  1. IO操作往往都是和外设交互,比如键盘、鼠标、打印机、磁盘。而最常见的就是内存与磁盘的交互,要知道磁盘是机械设备,需要机械运转来存取数据,所以比较慢。
  2. IO本质是:等+拷贝时间往往消耗在等上,等待键盘输入就绪、文件描述符就绪、硬件中断就绪…

  外设就绪慢是相较于 CPU 来说的,它本身是很快,我们感知不到。
  IO的拷贝很快的,慢大部分时间都花在等上,所以接下来我们就从“等”下手,去解决IO慢的问题。

IO 效率高?单位时间内,传输的数据量越大,IO 效率越高。

下面讲解的五种IO模型,我们从一个钓鱼例子引入:

  • 张三:全神贯注的盯着鱼漂,本着鱼漂不动我不动的原则,尽管马蜂扑他脸上。(阻塞)
  • 李四:不会因为鱼不上钩就紧紧盯着什么也不干,而是边做其他事情,刷刷快手抖音,写写博客啥的。(非阻塞)
  • 王五(聪明人):鱼竿顶部加铃铛,他比李四好一些,不用时不时地去看鱼漂。(信号驱动)
  • 赵六(富人):拖来一卡车100支鱼竿,全部用来钓鱼,然后只用左右检查是否有鱼竿钓到鱼。(多路复用)
    在这里插入图片描述
  • 田七(大老板):他知道他不是喜欢钓鱼,而是喜欢吃鱼。派小王去钓鱼,他干自己的事,到时候负责吃就行。(异步IO)

一、阻塞IO

  张三钓鱼的例子就是阻塞IO,它的特点是在内核将数据准备好之前,系统调⽤会⼀直等待。所有的套接字,默认都是阻塞⽅式。阻塞IO是最常见的IO模型。如下应用程序与内核的交互:

在这里插入图片描述

二、非阻塞IO

  ⾮阻塞IO:如果内核还未将数据准备好,系统调⽤仍然会直接返回,并且返回EWOULDBLOCK错误码。
  ⾮阻塞IO往往需要程序员循环的⽅式反复尝试读写⽂件描述符,这个过程称为轮询。这对CPU来说是较⼤的浪费,⼀般只有特定场景下才使⽤。

在这里插入图片描述

阻塞和⾮阻塞关注的是程序在等待调⽤结果(消息,返回值)时的状态。

  • 阻塞调⽤是指调⽤结果返回之前,当前线程会被挂起,调⽤线程只有在得到结果之后才会返回。
  • ⾮阻塞调⽤指在不能⽴刻得到结果之前,该调⽤不会阻塞当前线程。

文件默认情况下就是阻塞IO不用我们去修改,那么我们想要设置非阻塞IO要怎么做呢?

  • 方法一:在文件open打开时添加O_NONBLOCK标准位即可。
    如果在文件打开之后想要设非阻塞IO呢?
  • 方法二:使用函数fcntl,需要包含头文件unistd.hfcntl.h
int fcntl(int fd, int cmd, ... /* arg */ );

参数:

  • fd:文件描述符(如 ```socket``、普通文件等)。
  • cmd:控制命令(如 F_GETFL、F_SETFL等)。
    • F_GETL:获取当前文件描述符的标志,如 O_RDONLY、O_NONBLOCK等。
    • F_SETFL:设置文件描述符的标志。
  • arg:可选参数,取决于 cmd

返回值:

  • 成功时返回值取决于 cmd,F_GETFL成功时返回状态标志符,F_SETFL成功时返回0,失败时都返回-1
  • 失败时返回 -1,并设置 errno(如 EBADF 无效描述符)。

获取原标志符:int fg = fcntl(fd,F_GETFL);
设置O_NONBLOCK标志位:fcntl(fd, F_SETFL, fg | O_NONBLOCK)

  我们以read为例,当将文件设为非阻塞后,我们再去读取数据,即使数据没就绪,也不会把程序挂起,而是直接返回一个小于0的结果继续往下执行。所以数据并不一定一次read就读取到,需要我们反复去read,也就是轮询。
  不过还有一个问题,read失败返回值小于0,因为数据未就绪返回值也是小于0,那么我们怎么区分呢?其实这两种结果都有不同的erron错误参数,到时候拿erron去匹配就行,即:

  • EWOULDBLOCK或EAGAIN:都表示数据未就绪。因为历史版本原因所以有两个版本,它们的值都是11,任意使用一个即可。
  • EINTR:因信号中断导致的读书失败。
  • 其他:read读取错误。

测试示例:

#include <fcntl.h>
#include <unistd.h>
#include <iostream>
using namespace std;
int main()
{int fd = 0;//获取标志符int fn = fcntl(fd, F_GETFL);//增加O_NONBLOCK并设置fcntl(fd, F_SETFL, fn | O_NONBLOCK);int count = 0;while(1){char buffer[1024];int n = read(fd, buffer, sizeof(buffer)-1);if(n > 0){buffer[n] = '\0';cout<<buffer<<endl;sleep(1);}else if(n < 0){if(errno == EAGAIN || errno == EWOULDBLOCK){cout<<"文件未就绪..."<<endl;sleep(2);}else if(errno == EINTR){cout<<"信号中断..."<<endl;continue;}else{perror("read fail\n");break;}}else{break;}}return 0;
}

三、信号驱动IO

信号驱动IO:内核将数据准备好的时候,使⽤SIGIO信号通知应⽤程序进⾏IO操作。

在这里插入图片描述
工作流程

  • 注册信号处理程序:应用进程首先使用 sigaction系统调用,建立针对特定信号(通常是 SIGIO)的信号处理程序。在这一步,进程告知内核,当特定的 I/O 事件发生时,应该触发哪个信号处理函数。
  • 设置文件描述符:应用进程需要将相关的文件描述符(如套接字描述符)设置为信号驱动 I/O 模式,并指定该文件描述符的属主(通常使用fcntl 系统调用的 F_SETOWN命令设置属主为当前进程 )。这一步确保内核知道当 I/O 事件就绪时,应该向哪个进程发送信号。
  • 内核等待数据:完成上述设置后,应用进程可以继续执行其他任务,而内核开始等待数据到达。当数据报准备好(比如有数据到达套接字 )时,内核会向应用进程发送预先设置好的信号(如SIGIO )。
  • 信号处理:应用进程接收到SIGIO 信号后,会暂停当前正在执行的任务,转而执行之前注册的信号处理程序。在信号处理程序中,通常会调用诸如recvfrom 这样的函数来读取数据。在数据从内核拷贝到用户空间的应用缓冲区期间,进程会阻塞(这是信号处理函数内部执行具体 I/O 操作时的阻塞 ),直到数据拷贝完成。
  • 处理数据:数据读取完成后,信号处理程序执行结束,进程恢复之前被暂停的任务,或者开始对读取到的数据进行处理。

四、IO多路复用

  IO多路复用允许单个线程/进程同时监控多个文件描述符(如套接字、管道等)的 I/O 事件,并在任一描述符就绪时进行读写操作。它是高并发网络编程的核心技术之一。是真正意义上的高效 I/O 处理机制,它在单位时间内增加了传输效率,而其他四个只是在利用等的时间而已,并没有提高IO效率。
在这里插入图片描述

核心思想

  • 统一监控:通过系统调用(如select、poll、epoll)一次性注册多个文件描述符,由内核通知哪些描述符已就绪(可读/可写/异常)。
  • 避免阻塞轮询:无需为每个描述符创建独立线程,节省资源。
  • 单线程高并发:一个线程即可处理成千上万的连接(如 Nginx、Redis 的底层模型)。

  关于IO多路复用的很重要,涉及select/poll/epoll,有繁多的细节和复杂的底层逻辑,统一放在下一章进行讲解。

五、异步IO

在这里插入图片描述

  核心思想是 “发起 I/O 请求后立即返回,由内核完成所有操作(包括数据拷贝),并通过回调或信号通知进程结果”。与同步 I/O 不同,进程无需等待 I/O 完成即可继续执行其他任务,真正实现 非阻塞 和 完全异步。

异步IO特性

  • 非阻塞调用:调用 I/O 函数(如 aio_read)立即返回,不阻塞进程。
  • 内核全权处理:内核负责数据准备、拷贝到用户空间,全程无需进程参与。
  • 通知机制:操作完成后,内核通过回调、信号或事件通知进程。
  • 全程无等待:进程从发起请求到获取结果均无需阻塞,最大化利用 CPU。
IO模型控制方式优势劣势
阻塞 I/O进程阻塞等待数据编程简单无法并发处理多 I/O
非阻塞 I/O轮询检查数据是否就绪可同时处理其他任务轮询消耗 CPU
I/O多路复用select/epoll统一监控高并发支持
信号驱动 I/O内核信号通知无轮询,延迟低信号处理复杂,不适合高频场景
异步 I/O (AIO)内核完成所有操作后回调真正的异步,全程无阻塞实现复杂,部分系统支持不完善

非常感谢您能耐心读完这篇文章。倘若您从中有所收获,还望多多支持呀!
在这里插入图片描述

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

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

相关文章

第十二节:粒子系统:海量点渲染

第十二节&#xff1a;粒子系统&#xff1a;海量点渲染 引言 粒子系统是创造动态视觉效果的神器&#xff0c;从漫天繁星到熊熊火焰&#xff0c;从魔法特效到数据可视化&#xff0c;都离不开粒子技术。Three.js提供了强大的粒子渲染能力&#xff0c;可轻松处理百万级粒子。本文将…

LeetCode Day5 -- 二叉树

目录 1. 啥时候用二叉树&#xff1f; &#xff08;1&#xff09;典型问题 &#xff08;2&#xff09;核心思路 2. BFS、DFS、BST 2.1 广度优先搜索BFS &#xff08;1&#xff09;适用任务 &#xff08;2&#xff09;解决思路​​&#xff1a;使用队列逐层遍历 2.2 深度…

<c1:C1DateTimePicker的日期时间控件,控制日期可以修改,时间不能修改,另外控制开始时间的最大值比结束时间小一天

两个时间控件 <c1:C1DateTimePicker Width"170" EditMode"DateTime" CustomDateFormat"yyyy-MM-dd" CustomTimeFormat"HH:mm:ss" Style"{StaticResource ListSearch-DateTimePicker}" x:Name"dateTimePicker"…

文件完整性监控工具:架构和实现

文件完整性监控(FIM)作为一道关键的防御层&#xff0c;确保系统和网络中文件及文件夹的完整性与安全性。文件完整性监控工具通过监控关键文件的变更并检测未经授权的修改&#xff0c;提供关于潜在安全漏洞、恶意软件感染和内部威胁的早期警报。为了使文件完整性监控工具发挥实效…

Linux信号量和信号

1.温故知新上一篇博客&#xff0c;我们又知道了一种进程间通信的方案&#xff1a;共享内存。它是在物理内存中用系统调用给我们在物理内存开辟一个共享内存&#xff0c;可以由多个进程的页表进行映射&#xff0c;共享内存不和管道一样&#xff0c;它的生命周期是随内核的&#…

腾讯测试岗位面试真题分析

以下是对腾讯测试工程师面试问题的分类整理、领域占比分析及高频问题精选&#xff08;基于​​92道问题&#xff0c;总出现次数118次​​&#xff09;。问题按​​7大技术领域​​划分&#xff0c;高频问题标注优先级&#xff08;1-5&#x1f31f;&#xff09;&#xff1a; 不…

全面解析远程桌面:功能实现、性能优化与安全防护全攻略

远程桌面技术已成为工作与生活中不可或缺的协作工具&#xff0c;但在实际应用中&#xff0c;用户常遇到连接失败、卡顿延迟、安全隐患等问题。本文从远程桌面功能原理、网络与性能优化、安全防护策略、跨平台兼容性等角度&#xff0c;详细解析常见问题的解决方案&#xff0c;并…

【问题】Mybatis-plus框架使用@Select注解编写查询SQL,json字段查询转换失败

问题描述在使用mybaits-plus的时候定义的Mapper接口实现了BaseMapper&#xff0c;没有编写Mapper对应的xml&#xff0c;大部分查询使用框架的接口进行查询基本属性返回都是正常&#xff0c;复杂对象在sql中会进行查询&#xff0c;但是返回对象中却未包含相关属性。问题原因 没有…

Python多线程实现大文件下载

Python多线程实现大文件下载 在互联网时代&#xff0c;文件下载是日常操作之一&#xff0c;尤其是大文件&#xff0c;如软件安装包、高清视频等。然而&#xff0c;网络条件不稳定或带宽有限时&#xff0c;下载速度会变得很慢&#xff0c;令人抓狂。幸运的是&#xff0c;通过多线…

【R语言】RStudio 中的 Source on Save、Run、Source 辨析

RStudio 中的 Source on Save、Run、Source 辨析 在使用 RStudio 进行 R 语言开发时&#xff0c;我们会在主界面左上角看见三个按钮&#xff1a;Source on Save、Run、Source 。 本文将带你从概念、使用方法、快捷键、使用场景以及注意事项等方面详细解析这三个功能。 文章目录…

蓝桥杯算法之搜索章 - 4

目录 文章目录 前言 一、记忆化搜索 二、题目概略 三、斐波拉契数 四、Function 五、天下第一 六、滑雪 总结 亲爱的读者朋友们&#xff0c;大家好啊&#xff01;不同的时间&#xff0c;相同的地点&#xff0c;今天又带来了关于搜索部分的讲解。接下来我将接着我前面文章的内容…

抗量子加密技术前瞻:后量子时代的密码学革命

目录抗量子加密技术前瞻&#xff1a;后量子时代的密码学革命1. 量子计算威胁现状1.1 量子霸权里程碑1.2 受威胁算法1.3 时间紧迫性2. 抗量子密码学体系2.1 技术路线对比2.2 数学基础革新3. 标准化进程3.1 NIST PQC标准化时间线3.2 当前推荐算法4. 技术实现方案4.1 Kyber密钥交换…

基于STM32设计的矿山环境监测系统(NBIOT)_262

文章目录 一、前言 1.1 项目介绍 【1】开发背景 【2】研究的意义 【3】最终实现需求 【4】项目硬件模块组成 1.2 设计思路 【1】整体设计思路 【2】上位机开发思路 1.3 项目开发背景 【1】选题的意义 【2】摘要 【3】国内外相关研究现状 【5】参考文献 1.4 开发工具的选择 【1】…

电脑如何安装win10专业版_电脑用u盘安装win10专业版教程

电脑如何安装win10专业版&#xff1f;电脑还是建议安装win10专业版。Win分为多个版本&#xff0c;其中家庭版&#xff08;Home&#xff09;和专业版&#xff08;Pro&#xff09;是用户选择最多的两个版本。win10专业版在功能以及安全性方面有着明显的优势&#xff0c;所以电脑还…

多语言文本 AI 情感分析 API 数据接口

多语言文本 AI 情感分析 API 数据接口 AI / 文本处理 AI 模型快速分析文本情感倾向 多语言文本 / 情感分析。 1. 产品功能 支持多语言文本情感分析&#xff1b;基于特定 AI 模型&#xff0c;快速识别文本情感倾向&#xff1b;适用于评论分析、舆情监控等场景&#xff1b;全接…

【R语言】R语言的工作空间映像(workspace image,通常是.RData)详解

R语言的工作空间映像&#xff08;.RData&#xff09;详解 在使用 R 语言时&#xff0c;你可能会注意到&#xff0c;每次退出 R 会弹出一个提示&#xff1a; Save workspace image? [y/n/c] 如果你使用的是 Rstudio 这个 IDE 来进行R语言的开发&#xff0c;那么可能弹出的提示…

在线 A2C实践

在线 A2C&#xff08;Actor-Critic&#xff09;算法在推荐系统中的实践&#xff0c;核心是将推荐过程建模为实时交互的强化学习问题&#xff0c;通过 Actor 生成推荐策略、Critic 评估策略价值&#xff0c;实现 “决策 - 反馈 - 更新” 的闭环。从样本设计到最终上线&#xff0…

Eclipse RCP产品动态模块设计

文章目录 遇到问题具体实践效果演示应用下载 遇到问题 如果你是一个To C产品的设计者&#xff0c;势必会遇到用户需求高度分化的场景&#xff0c;随之而来的是繁杂的功能列表&#xff0c;如何让用户只接触与其任务直接相关的功能&#xff0c;隐藏无关元素&#xff1f; 具体实…

NLP自然语言处理: FastText工具与迁移学习基础详解

FastText工具与迁移学习基础详解 一、知识框架总览 FastText工具核心功能与应用场景FastText模型架构与工作原理层次Softmax加速机制哈夫曼树概念与构建方法 二、FastText工具核心解析 2.1 功能定位 双重核心功能 文本分类&#xff1a;可直接用于文本分类任务&#xff0c;快速生…

uni-app 生命周期详解

概述 uni-app 基于 Vue.js 框架开发&#xff0c;其生命周期包含了三个层面&#xff1a; 应用生命周期&#xff1a;App.vue 的生命周期页面生命周期&#xff1a;各个页面的生命周期Vue 组件生命周期&#xff1a;Vue.js 原生的组件生命周期 这三种生命周期在不同场景下会按特定顺…