当前位置: 首页 > news >正文

Linux I/O 多路复用机制详解

文章目录

  • 1 文件描述符(File Descriptor)
    • 1.1 什么是文件描述符?
    • 1.2 文件描述符与文件的关系
  • 2 文件描述符集合(File Descriptor Set)
    • 2.1 什么是文件描述符集合?
    • 2.2 `fd_set` 结构体
  • 3 `select()` 函数的工作原理
    • 3.1 `select()` 函数概述
    • 3.2 `select()` 的工作步骤
  • 4 `poll()` 函数的工作原理
    • 4.1 `poll()` 函数概述
    • 4.2 `pollfd` 结构体
    • 4.3 `poll()` 的工作步骤
  • 5 `select()` 和 `poll()` 的底层比较
  • 6 总结
  • 参考链接
  • 封面

本文将详细解释文件描述符、文件描述符集合,以及 select()poll() 的底层工作原理,以帮助理解 Linux 系统的 I/O 多路复用机制。

1 文件描述符(File Descriptor)

1.1 什么是文件描述符?

在 Unix 和 Linux 系统中,文件描述符(File Descriptor, FD) 是一个非负整数,用于表示已打开的文件、网络套接字、管道等 I/O 资源。每个进程都有一个文件描述符表,这个表记录了进程当前打开的所有文件。

1.2 文件描述符与文件的关系

当一个进程打开一个文件(或其他 I/O 资源),内核会为这个文件分配一个文件描述符,并将其返回给进程。这个文件描述符可以用来标识和访问该文件。例如:

int fd = open("example.txt", O_RDWR);

在这段代码中,open() 函数返回的 fd 就是文件描述符,它指向已打开的 example.txt 文件。之后,进程可以使用 fd 来读取或写入文件。

2 文件描述符集合(File Descriptor Set)

2.1 什么是文件描述符集合?

文件描述符集合 是一组文件描述符的集合,通常用于 I/O 多路复用函数 select() 中。它们用来表示一组文件描述符的状态(如可读、可写或有错误)。在 Linux 中,文件描述符集合通常由 fd_set 结构体表示。

2.2 fd_set 结构体

fd_set 是一个位图,每个比特位对应一个文件描述符。如果集合中包含某个文件描述符,则该比特位被设置为 1,否则为 0。以下是常用的操作:

  • FD_ZERO:清空集合(将所有比特位设置为 0)。
  • FD_SET:将一个文件描述符加入集合(将对应比特位设置为 1)。
  • FD_CLR:从集合中移除一个文件描述符(将对应比特位设置为 0)。
  • FD_ISSET:检查某个文件描述符是否在集合中(检查对应比特位是否为 1)。

3 select() 函数的工作原理

3.1 select() 函数概述

select() 是一种 I/O 多路复用技术,用于同时监视多个文件描述符的状态(如可读、可写或有错误),并在其中一个或多个文件描述符的状态发生变化时返回。select() 的函数签名如下:

int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout);

3.2 select() 的工作步骤

  1. 初始化文件描述符集合

    • 使用 FD_ZERO 清空集合,然后用 FD_SET 将感兴趣的文件描述符加入集合。
  2. 调用 select()

    • 内核将挂起进程,并同时监控 readfdswritefdsexceptfds 中的文件描述符,直到其中一个或多个文件描述符的状态发生变化,或者超时。
  3. 内核检查文件描述符状态

    • 内核会遍历所有文件描述符,检查它们的状态。如果一个文件描述符变得可读、可写或发生异常,内核会设置相应集合中的比特位。
  4. select() 返回并处理结果

    • select() 返回文件描述符集合的状态。应用程序可以使用 FD_ISSET 检查哪些文件描述符已经准备好进行 I/O 操作。

4 poll() 函数的工作原理

4.1 poll() 函数概述

poll() 是另一种 I/O 多路复用技术,与 select() 类似,但它使用不同的方式来表示文件描述符集合。poll() 的函数签名如下:

int poll(struct pollfd *fds, nfds_t nfds, int timeout);

4.2 pollfd 结构体

pollfd 结构体包含了一个文件描述符及其感兴趣的事件和返回的状态:

struct pollfd {int fd;         /* 监视的文件描述符 */short events;   /* 感兴趣的事件 */short revents;  /* 返回的事件 */
};

4.3 poll() 的工作步骤

  1. 初始化 pollfd 结构体数组

    • 填充 pollfd 结构体数组,指定每个文件描述符和感兴趣的事件。
  2. 调用 poll()

    • 内核将挂起进程,并监视 fds 数组中所有文件描述符的状态,直到某个文件描述符的状态发生变化,或者超时。
  3. 内核检查文件描述符状态

    • 内核逐个检查 fds 数组中的文件描述符,并更新 revents 字段,表示实际发生的事件。
  4. poll() 返回并处理结果

    • poll() 返回后,应用程序检查 revents 字段,确定哪些文件描述符已经准备好进行 I/O 操作。

5 select()poll() 的底层比较

  • 效率

    • select() 使用位图来表示文件描述符集合,这意味着它最多只能监视 FD_SETSIZE(通常是 1024)个文件描述符。同时,由于每次调用 select() 都需要重新设置位图集合,因此在处理大量文件描述符时效率较低。
    • poll() 使用数组来表示文件描述符集合,理论上可以监视任意数量的文件描述符。而且 poll() 不需要每次重置整个数组,只需更新感兴趣的事件即可,因此效率更高。
  • 灵活性

    • poll() 提供了对更多事件类型的支持(如 POLLPRI,表示高优先级数据),而 select() 只支持基本的可读、可写和异常事件。
  • 扩展性

    • select() 的文件描述符数量受限于 FD_SETSIZE,而 poll() 没有这个限制,因此在需要处理大量文件描述符的场景,poll() 更具扩展性。

6 总结

  • 文件描述符 是进程与文件或其他 I/O 资源交互的句柄,每个进程都有自己的一组文件描述符。
  • 文件描述符集合 是多个文件描述符的集合,通常用于 select() 函数中,以同时监视多个文件描述符的状态。
  • select() 通过使用位图集合来监视多个文件描述符的状态,适合处理小数量的文件描述符。
  • poll() 通过使用数组来监视多个文件描述符的状态,适合处理大量文件描述符,且效率更高。

无论是 select() 还是 poll(),它们的核心作用都是提供一种机制来同时监视多个文件描述符的状态,并在这些文件描述符的状态发生变化时通知应用程序,从而实现高效的 I/O 多路复用。


参考链接

  • Linux man page for select
  • Linux man page for poll

封面

由 DALL-E-3 生成
在这里插入图片描述

相关文章:

Linux I/O 多路复用机制详解

文章目录 1 文件描述符(File Descriptor)1.1 什么是文件描述符?1.2 文件描述符与文件的关系 2 文件描述符集合(File Descriptor Set)2.1 什么是文件描述符集合?2.2 fd_set 结构体 3 select() 函数的工作原理…...

第43课 Scratch入门篇:雪花随风飘

雪花随风飘 故事背景: 雪花轻轻地从灰蒙蒙的天空中飘落下来,它们像是天空中飘洒下来的羽毛,又像是冬日的精灵在翩翩起舞。每一片雪花都独一无二,它们在空中旋转、飘荡,最终缓缓降落在屋顶、树枝、街道和行人的肩头。 程序原理: 众多的雪花肯定是克隆功能,降落过程是通过…...

VueUse 基于 Vue 3 Composition API 的高质量 Hooks 库

VueUse 是什么? VueUse 是基于 Vue 3 Composition API 的高质量 Hooks 库。例如获取滚动的距离 VueUse 官网:VueUse | VueUse VueUse 什么使用? 1、通过npm安装 VueUse npm i @vueuse/core 2、搜索需要使用的函数,例如搜索 useScroll 滚动 3、使用useScroll 滚动函数 …...

ARM CoreLink 系列 5.1.1 -- CI-700 System Address Map 】

文章目录 System Address MapRN SAMRN SAM memory regions and target typesSAM memory region size configurationRN SAM target ID selectionSystem Address Map 所有的CHI 命令都包含一个 Source ID 和 Target ID, 其中 Source ID 可以来自于 RN Node, Target ID 可以来自…...

【数据结构】二叉树(一)

目录 1. 树型结构 概念 树的表示形式 ​编辑 2. 二叉树(重点) 2.1 概念 2.2 二叉树的性质 2.3 二叉树的存储 2.4 二叉树的遍历 前中后序遍历 层序遍历: 2.5二叉树的基本操作 本篇主要理解树和二叉树相关概念,二叉树遍…...

使用duplicate搭建备库或者级联备库

使用duplicate搭建备库或者级联备库: 主库或者源端: 1. 创建pfile,更改&添加部分参数、传输到备库; 2. 主库(或者源端)的tnsnames.ora文件添加 备库的连接信息 备库: 1. 备库添加静态监听 2…...

【存储学习笔记】4:快照(Snapshot)技术的实现方式

1 快照 1.1 动机 在上一篇《备份》里提到,热备份就是在执行操作时,服务器需要正常处理来自用户或应用对数据的更新,这样能够保证数据7*24小时可用(在很多服务里这是必要的)。 而热备份的困难就是如何保证数据的一致…...

数根(字符串数根公式)

公式&#xff1a;a的数根(a-1)%91&#xff1b; #include <bits/stdc.h> using namespace std; string s; long long sum; int main(){cin>>s;for(int i0;i<s.size();i){sums[i]-0;}cout<<(sum-1)%91; }...

C语言之文件操作上卷(二十一)(逆行人生-2024)

&#x1f4e3;&#x1f4e3;&#x1f4e3;&#x1f4e3;&#x1f4e3;&#x1f4e3;&#x1f4e3;&#x1f4e3; ✏️作者主页&#xff1a;枫霜剑客 &#x1f4cb; 系列专栏&#xff1a;C语言知识学习归纳总结&#xff08;逐梦篇专栏合集&#xff09; &#x1f332;上一篇: C语…...

【微服务架构实战】结合实际案例进行微服务架构的设计与实现

微服务架构实战 结合实际案例进行微服务架构的设计与实现 引言 微服务架构&#xff08;Microservices Architecture&#xff09;是一种将大型应用程序拆分成一组小型、独立的服务的方法&#xff0c;每个服务都专注于特定的业务功能&#xff0c;并能够独立开发、部署和扩展。这…...

为什么要有二级指针

提示&#xff1a;文章 文章目录 前言一、背景二、 2.1 2.2 总结 前言 前期疑问&#xff1a; 本文目标&#xff1a; 一、背景 之前一直疑问为什么要有二级指针&#xff0c;一直没有写这个帖子&#xff0c;今天整理了一下&#xff0c;收获颇丰 二、 2.1 // 增加对二级指针…...

如何保证数据不丢失?(死信队列)

死信队列 1、什么是死信 死信通常是消息在特定的场景下表现&#xff1a; 消息被拒绝访问消费者发生异常&#xff0c;超过重试次数消息的Expiration过期时长或者队列TTL过期时间消息队列到达最大容量 maxLength 2、什么是死信队列 只由死信构成的消息队列是死信队列 死信队…...

树莓派开发笔记01-树莓派的系统烧录以及初次开机配置

github主页&#xff1a;https://github.com/snqx-lqh gitee主页&#xff1a;https://gitee.com/snqx-lqh 本项目github地址&#xff1a;https://github.com/snqx-lqh/RaspberryPiLearningNotes 本项目gitee地址&#xff1a;https://gitee.com/snqx-lqh/RaspberryPiLearningNote…...

微信答题小程序产品研发-后端开发

在开发答题小程序的后端服务和数据库设计时&#xff0c;需要考虑API的设计、数据库模型的构建以及数据的安全性和一致性。 这里我采用了云开发&#xff0c;后端语言是Node&#xff0c;数据库是NoSql&#xff0c;然后我简单整理了各个功能模块的后端开发概要和数据库设计。 1. …...

回溯算法——LeetCode37 解数独

题目 力扣题目链接 思路 卡哥的思路&#xff0c;注意看他解释为什么是“二维回溯”。我的思路&#xff0c;类似y总解决 N 皇后问题时的第二种方法&#xff0c;即从左上到右下枚举棋盘的每个位置。 至于为什么与 N 皇后问题不一样&#xff0c;我认为是因为它每一行不止放一个…...

【CPP】继承语法详解与菱形继承

关于我&#xff1a; 睡觉待开机&#xff1a;个人主页 个人专栏: 《优选算法》《C语言》《CPP》 生活的理想&#xff0c;就是为了理想的生活! 作者留言 PDF版免费提供&#xff1a;倘若有需要&#xff0c;想拿我写的博客进行学习和交流&#xff0c;可以私信我将免费提供PDF版。…...

数据结构(6.2_1)——领接矩阵法

图的存储——邻接矩阵法 邻接矩阵&#xff08;Adjacency Matrix&#xff09;是一种使用二维数组来表示图的方法。在这种表示法中&#xff0c;矩阵的行和列都对应图的顶点。 特点 对于无向图&#xff0c;如果顶点i与顶点j之间有边&#xff0c;则矩阵的第i行第j列&#xff08;…...

诈骗未成功是否构成犯罪?

诈骗未成功不一定构成犯罪。在刑法上&#xff0c;构成诈骗罪需要满足特定的构成要件&#xff0c;包括有非法占有的目的、实施了虚构事实或隐瞒真相的行为、对方因此陷入错误认识并处分财产、行为人或第三方取得财产、被害人遭受财产损失。如果诈骗行为未能成功&#xff0c;即被…...

网络协议栈应用层的意义(内含思维导图和解析图通俗易懂超易理解)

绪论​&#xff1a; “节省时间的方法就是全力以赴的将所要做的事情完美快速的做完&#xff0c;不留返工重新学习的时间&#xff0c;才能省下时间给其他你认为重要的东西。” 本章主要讲到OSI网络协议栈中的应用层的作用和再次在应用层的角度理解协议的具体意义&#xff0c;以及…...

【NXP-MCXA153】i2c驱动移植

介绍 ‌I2C总线由飞利浦公司开发&#xff0c;是一种串行单工通信总线&#xff0c;它主要用于连接微控制器和其他外围设备并在总线上的器件之间传送信息&#xff08;需要指定设备地址&#xff09;&#xff1b;常见的i2c设备有EEPROM、触摸屏、各种IoT传感器、时钟模块等&#x…...

离线语音技术如何重塑智能照明:从核心原理到产品实战

1. 从“在线”到“离线”&#xff1a;智能照明交互的范式转变作为一名在智能家居领域摸爬滚打了十来年的从业者&#xff0c;我亲眼见证了智能照明从最初的手机APP遥控&#xff0c;到后来的智能音箱联动&#xff0c;再到如今离线语音技术的兴起。每次技术迭代&#xff0c;都不仅…...

手把手教你用STC89C52单片机驱动DS1302时钟模块(附完整代码)

STC89C52与DS1302时钟模块实战指南&#xff1a;从硬件搭建到代码实现 1. 项目概述与硬件准备 在嵌入式系统开发中&#xff0c;实时时钟(RTC)功能是许多项目的核心需求。STC89C52作为经典的51系列单片机&#xff0c;与DS1302时钟模块的组合&#xff0c;为开发者提供了经济实惠且…...

观察Taotoken用量看板如何帮助团队控制API成本

&#x1f680; 告别海外账号与网络限制&#xff01;稳定直连全球优质大模型&#xff0c;限时半价接入中。 &#x1f449; 点击领取海量免费额度 观察Taotoken用量看板如何帮助团队控制API成本 作为团队的技术负责人&#xff0c;引入大模型API后&#xff0c;成本的可观测性与可…...

ElevenLabs旁遮普语TTS突然失真?3步定位Gurmukhi Unicode变体(U+0A02/U+0A3C/U+0A4D)引发的音素错位故障

更多请点击&#xff1a; https://intelliparadigm.com 第一章&#xff1a;ElevenLabs旁遮普文语音合成异常现象综述 ElevenLabs 目前官方文档明确标注支持旁遮普语&#xff08;Gurmukhi script, language code: pa&#xff09;&#xff0c;但在实际调用其 REST API 进行语音合…...

ElevenLabs老年语音情感衰减难题破解(附可复用的Prosody增强JSON Schema与实测MOS提升2.1分)

更多请点击&#xff1a; https://intelliparadigm.com 第一章&#xff1a;ElevenLabs老年男性语音情感衰减现象的本质剖析 ElevenLabs 的老年男性语音模型&#xff08;如 “Antoni” 或 “Josh”&#xff09;在高语速、长句或情绪密集场景下&#xff0c;常出现语调扁平化、微停…...

Node.js服务端应用无缝集成Taotoken提供多模型AI能力

&#x1f680; 告别海外账号与网络限制&#xff01;稳定直连全球优质大模型&#xff0c;限时半价接入中。 &#x1f449; 点击领取海量免费额度 Node.js服务端应用无缝集成Taotoken提供多模型AI能力 将大模型能力集成到Node.js后端服务中&#xff0c;可以快速为应用增加智能对…...

从零开始:如何在Windows电脑上完美使用Switch手柄的完整教程

从零开始&#xff1a;如何在Windows电脑上完美使用Switch手柄的完整教程 【免费下载链接】JoyCon-Driver A vJoy feeder for the Nintendo Switch JoyCons and Pro Controller 项目地址: https://gitcode.com/gh_mirrors/jo/JoyCon-Driver 你是否曾经想过在Windows电脑上…...

如何用ComfyUI-WanVideoWrapper开启你的AI动态内容创作之旅

如何用ComfyUI-WanVideoWrapper开启你的AI动态内容创作之旅 【免费下载链接】ComfyUI-WanVideoWrapper 项目地址: https://gitcode.com/GitHub_Trending/co/ComfyUI-WanVideoWrapper 在AI视频生成的世界里&#xff0c;你是否曾想象过将文字描述转化为生动的动态画面&am…...

给操作系统爱好者的RISC-V中断实战指南:从SiFive Unleashed开发板到Xv6内核代码

RISC-V中断机制深度解析&#xff1a;从硬件触发到Xv6内核实战 1. RISC-V中断体系架构全景 RISC-V中断系统采用分层设计理念&#xff0c;硬件与软件协同构成了完整的异常处理框架。作为开源指令集架构&#xff0c;RISC-V的中断设计既保持了精简性&#xff0c;又通过可扩展机制满…...

在Windows电脑上畅享酷安社区的完整指南:桌面端酷安客户端终极教程

在Windows电脑上畅享酷安社区的完整指南&#xff1a;桌面端酷安客户端终极教程 【免费下载链接】Coolapk-UWP 一个基于 UWP 平台的第三方酷安客户端 项目地址: https://gitcode.com/gh_mirrors/co/Coolapk-UWP 想要在大屏幕上舒适地浏览酷安社区吗&#xff1f;厌倦了手机…...