I/O多路复用:select、poll和epoll区别

IO多路复用之select、poll、epoll之间的区别总结 select、poll、epoll都是IO多路复用的机制。IO多路复用就是通过一种机制,让一个进程/线程可以监视多个描述符,一旦某个描述符就绪(一般是读写就绪),能够通知应用程序进行相应的读写操作。I/O复用虽然能同时监听多个文件描述符,当其本质上还是同步IO模型,因为需要在读写事件就绪后程序自己负责进行读写事件的处理,而这个读写过程是阻塞的。如果要实现并发,只能使用多进程/多线程等编程手段了。 ... 阅读详情

声明:来源牛客网课程

放在此处便于翻阅,侵删

I/O 多路复用使得程序能同时监听多个文件描述符,能够提高程序的性能,Linux 下实现 I/O 多路复用的
系统调用主要有 select、poll 和 epoll。

1. select

主旨思想:

  1. 首先要构造一个关于文件描述符的列表,将要监听的文件描述符添加到该列表中。
  2. 调用一个系统函数,监听该列表中的文件描述符,直到这些描述符中的一个或者多个进行I/O
    操作时,该函数才返回。
    a.这个函数是阻塞
    b.函数对文件描述符的检测的操作是由内核完成的
  3. 在返回时,它会告诉进程有多少(哪些)描述符要进行I/O操作。
// sizeof(fd_set) = 128 1024
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/select.h>
int select(int nfds, fd_set *readfds, fd_set *writefds,
fd_set *exceptfds, struct timeval *timeout);
- 参数:
- nfds : 委托内核检测的最大文件描述符的值 + 1
- readfds : 要检测的文件描述符的读的集合,委托内核检测哪些文件描述符的读的属性
- 一般检测读操作
- 对应的是对方发送过来的数据,因为读是被动的接收数据,检测的就是读缓冲
区
- 是一个传入传出参数
- writefds : 要检测的文件描述符的写的集合,委托内核检测哪些文件描述符的写的属性
- 委托内核检测写缓冲区是不是还可以写数据(不满的就可以写)
- exceptfds : 检测发生异常的文件描述符的集合
- timeout : 设置的超时时间
struct timeval {
long tv_sec; /* seconds */
long tv_usec; /* microseconds */
};
- NULL : 永久阻塞,直到检测到了文件描述符有变化
- tv_sec = 0 tv_usec = 0, 不阻塞
- tv_sec > 0 tv_usec > 0, 阻塞对应的时间
- 返回值 :
- -1 : 失败
- >0(n) : 检测的集合中有n个文件描述符发生了变化
// 将参数文件描述符fd对应的标志位设置为0
void FD_CLR(int fd, fd_set *set);
// 判断fd对应的标志位是0还是1, 返回值 : fd对应的标志位的值,0,返回0, 1,返回1
int FD_ISSET(int fd, fd_set *set);
// 将参数文件描述符fd 对应的标志位,设置为1
void FD_SET(int fd, fd_set *set);
// fd_set一共有1024 bit, 全部初始化为0
void FD_ZERO(fd_set *set);

在这里插入图片描述
在这里插入图片描述

2. poll

#include <poll.h>
struct pollfd {
int fd; /* 委托内核检测的文件描述符 */
short events; /* 委托内核检测文件描述符的什么事件 */
short revents; /* 文件描述符实际发生的事件 */
};
struct pollfd myfd;
myfd.fd = 5;
myfd.events = POLLIN | POLLOUT;
int poll(struct pollfd *fds, nfds_t nfds, int timeout);
- 参数:
- fds : 是一个struct pollfd 结构体数组,这是一个需要检测的文件描述符的集合
- nfds : 这个是第一个参数数组中最后一个有效元素的下标 + 1
- timeout : 阻塞时长
0 : 不阻塞
-1 : 阻塞,当检测到需要检测的文件描述符有变化,解除阻塞
>0 : 阻塞的时长
- 返回值:
-1 : 失败
>0(n) : 成功,n表示检测到集合中有n个文件描述符发生变化

在这里插入图片描述
poll和select同样存在一个缺点就是,包含大量文件描述符的数组被整体复制于用户态和内核的地址空间之间,而不论这些文件描述符是否就绪,它的开销随着文件描述符数量的增加而线性增大。

  1. 它将用户传入的数组拷贝到内核空间
  2. 然后查询每个fd对应的设备状态:
  3. 如果设备就绪 在设备等待队列中加入一项继续遍历
  4. 若遍历完所有fd后,都没发现就绪的设备 挂起当前进程,直到设备就绪或主动超时,被唤醒后它又再次遍历fd。这个过程经历多次无意义的遍历。

没有最大连接数限制,因其基于链表存储,其缺点:

  1. 大量fd数组被整体复制于用户态和内核地址空间间,而不管是否有意义
  2. 如果报告了fd后,没有被处理,那么下次poll时会再次报告该fd

所以又有了epoll模型。

3. epoll

epoll模型修改主动轮询为被动通知,当有事件发生时,被动接收通知。所以epoll模型注册套接字后,主程序可做其他事情,当事件发生时,接收到通知后再去处理。

可理解为event poll,epoll会把哪个流发生哪种I/O事件通知我们。所以epoll是事件驱动(每个事件关联fd),此时我们对这些流的操作都是有意义的。复杂度也降到O(1)。

#include <sys/epoll.h>
创建一个新的epoll实例。在内核中创建了一个数据,这个数据中有两个比较重要的数据,一个是需要检
测的文件描述符的信息(红黑树),还有一个是就绪列表,存放检测到数据发送改变的文件描述符信息(双向
链表)。
int epoll_create(int size);
- 参数:
size : 目前没有意义了。随便写一个数,必须大于0
- 返回值:
-1 : 失败
> 0 : 文件描述符,操作epoll实例的

typedef union epoll_data {
void *ptr;
int fd;
uint32_t u32;
uint64_t u64;
} epoll_data_t;
struct epoll_event {
uint32_t events; /* Epoll events */
epoll_data_t data; /* User data variable */
};
常见的Epoll检测事件:
- EPOLLIN
- EPOLLOUT
- EPOLLERR
- 
对epoll实例进行管理:添加文件描述符信息,删除信息,修改信息
int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event);
- 参数:
- epfd : epoll实例对应的文件描述符
- op : 要进行什么操作
EPOLL_CTL_ADD: 添加
EPOLL_CTL_MOD: 修改
EPOLL_CTL_DEL: 删除
- fd : 要检测的文件描述符
- event : 检测文件描述符什么事情
- 
 检测函数
int epoll_wait(int epfd, struct epoll_event *events, int maxevents, int
timeout);
- 参数:
- epfd : epoll实例对应的文件描述符
- events : 传出参数,保存了发送了变化的文件描述符的信息
- maxevents : 第二个参数结构体数组的大小
- timeout : 阻塞时间
- 0 : 不阻塞
- -1 : 阻塞,直到检测到fd数据发生变化,解除阻塞
- > 0 : 阻塞的时长(毫秒)
- 返回值:
- 成功,返回发送变化的文件描述符的个数 > 0
- 失败 -1

Epoll 的工作模式:
LT 模式 (水平触发)
假设委托内核检测读事件 -> 检测fd的读缓冲区
读缓冲区有数据 - > epoll检测到了会给用户通知
a.用户不读数据,数据一直在缓冲区,epoll 会一直通知
b.用户只读了一部分数据,epoll会通知
c.缓冲区的数据读完了,不通知

== LT(level - triggered)是缺省的工作方式,并且同时支持 block 和 no-block socket。在这
种做法中,内核告诉你一个文件描述符是否就绪了,然后你可以对这个就绪的 fd 进行 IO 操 作。如果你不作任何操作,内核还是会继续通知你的 ==

ET 模式(边沿触发)
假设委托内核检测读事件 -> 检测fd的读缓冲区
读缓冲区有数据 - > epoll检测到了会给用户通知
a.用户不读数据,数据一致在缓冲区中,epoll下次检测的时候就不通知了
b.用户只读了一部分数据,epoll不通知
c.缓冲区的数据读完了,不通知

== ET(edge - triggered)是高速工作方式,只支持 no-block socket。在这种模式下,当描述
符从未就绪变为就绪时,内核通过epoll告诉你。然后它会假设你知道文件描述符已经就绪,
并且不会再为那个文件描述符发送更多的就绪通知,直到你做了某些操作导致那个文件描述
符不再为就绪状态了。但是请注意,如果一直不对这个 fd 作 IO 操作(从而导致它再次变成
未就绪),内核不会发送更多的通知(only once)。
ET 模式在很大程度上减少了 epoll 事件被重复触发的次数,因此效率要比 LT 模式高。epoll
工作在 ET 模式的时候,必须使用非阻塞套接口,以避免由于一个文件句柄的阻塞读/阻塞写
操作把处理多个文件描述符的任务饿死 ==

struct epoll_event {
uint32_t events; /* Epoll events */
epoll_data_t data; /* User data variable */
};

常见的Epoll检测事件:

  • EPOLLIN
  • EPOLLOUT
  • EPOLLERR
  • EPOLLET

在这里插入图片描述

4.总结

select,poll,epoll都是IO多路复用机制,即可以监视多个描述符,一旦某个描述符就绪(读或写就绪),能够通知程序进行相应读写操作。 但select,poll,epoll本质上都是同步I/O,因为他们都需要在读写事件就绪后自己负责进行读写,也就是说这个读写过程是阻塞的,而异步I/O则无需自己负责进行读写,异步I/O的实现会负责把数据从内核拷贝到用户空间。

select,poll实现需要自己不断轮询所有fd集合,直到设备就绪,期间可能要睡眠和唤醒多次交替。而epoll其实也需要调用epoll_wait不断轮询就绪链表,期间也可能多次睡眠和唤醒交替,但是它是设备就绪时,调用回调函数,把就绪fd放入就绪链表中,并唤醒在epoll_wait中进入睡眠的进程。虽然都要睡眠和交替,但是select和poll在“醒着”的时候要遍历整个fd集合,而epoll在“醒着”的时候只要判断一下就绪链表是否为空就行了,这节省了大量的CPU时间。这就是回调机制带来的性能提升。
select,poll每次调用都要把fd集合从用户态往内核态拷贝一次,并且要把current往设备等待队列中挂一次,而epoll只要一次拷贝,而且把current往等待队列上挂也只挂一次(在epoll_wait的开始,注意这里的等待队列并不是设备等待队列,只是一个epoll内部定义的等待队列)。这也能节省不少的开销。

表面上看epoll的性能最好,但是在连接数少并且连接都十分活跃的情况下,select和poll的性能可能比epoll好,毕竟epoll的通知机制需要很多函数回调。

参考:一文搞懂select、poll和epoll区别

Linux·I/O模式及select、poll、epoll详解 Linux·多路IO分析 阅读详情

相关推荐

星载SAR系统参数设计过程自动化方法研究

 本文提出了一种 SAR系统参数自动化设计的 方法。首先,针对部分参数仍需手工选取的现状 建立了最优化求解模型,并给出了 PRF 和波位位 置的优化选取结果,使参数设计流程更加高效便 捷。然后,针对 SAR 系统参数设计过程中部分技 术指标的评测结果不满足用户需求时无法自动调 节的现状,采用 PID 控制器对方位向天线尺寸、信 号带宽、PRF 等参数进行自动调节,使得方位分辨 率、距离分辨率、方位模糊比等技术指标向用户需 求值逐步靠近。通过仿真实验验证了该方法的可 行性,实现了SAR系统参数设计过程的自动化

qq_43416206的博客 1524

select、poll、epoll之间的区别(搜狗面试)

(1)select==>时间复杂度O(n) 它仅仅知道了,有I/O事件发生了,却并不知道是哪那几个流(可能有一个,多个,甚至全部),我们只能无差别轮询所有流,找出能读出数据,或者写入数据的流,对他们进行操作。所以select具有O(n)的无差别轮询复杂度,同时处理的流越多,无差别轮询时间就越长。 (2)poll==>时间复杂度O(n) poll本质上和select没...

3931

AI原生应用在UGC内容审核中的实战经验

AI原生应用(AI-Native Application)——以机器学习模型为核心驱动力,深度整合数据、算法、工程架构的完整系统——为破解这一三角难题提供了全新范式。全链路数据驱动:从数据采集、模型训练到决策优化,形成闭环自治系统,无需人工规则干预多模态深度理解:同时处理文本、图像、音频、视频等多类型内容,理解语义而非简单匹配特征自适应进化能力:通过人机协同反馈持续学习新型违规模式,模型周级迭代成为常态审核效率提升300%:单条视频审核耗时从2.3秒降至0.7秒。

AI算力网络与通信的博客 1149

Select、Poll、Epoll的使用和区别,多种IO的区别

IO多路复用的三种机制,以及区别,多种IO的区别

iuu77的博客 671

①Modbus TCP转Modbus RTU/ASCII网关同步采集无需编程高速轻松组网

MS-A1-50X1系列作为MODBUS TCP通信的服务器进行动作。可通过MODBUS TCP 通信,将 MS-A1-50X1 系列产品通过 RS485 采集的仪器仪表之类的值作为通信数 据输出到 PLC,上位机等。

2401_89571741的博客 1398

华为FusionCharge 720kW液冷直流快充桩主电流全路径深度详解

本文档详细介绍了华为FusionCharge 720kW液冷分体式直流充电系统的主电流路径全链路解析,适用于配套DS720-720LCNA1充电主机及DT600L1-CNA1液冷终端、DT250N2-CNA1自然冷终端的运维工作。内容涵盖从电网交流输入到电动汽车充电的全过程,重点解析交流门、整流正门、主控正门等五大柜门区域的核心元器件分布及功能,包括额定参数、安全规范、故障排查等关键运维知识。操作人员需持有高压电工证并通过专项培训,作业时必须严格遵守断电验电、穿戴PPE防护装备等安全红线。文档通过16个关键

2401_84939870的博客 750

I/O多路复用之select,poll,epoll的区别

一、关于select,poll,epoll三种IO模型,都属于多路IO就绪通知,提供了对大量文件描述符就绪检查的高性能方案,只不过实现方式有所不同:select原理概述:调用select时,会发生以下事情:(1)从用户空间拷贝fd_set到内核空间;(2)注册回调函数__pollwait;(3)遍历所有fd,对全部指定设备做一次poll(这里的poll是一个文件操作,它有两个...

weixin_34341229的博客 121

第三天:Python基础语法详解

Python代码规范与注释最佳实践 摘要: 本文深度解析Python缩进规则与代码结构的技术规范,包括缩进的底层原理、语法规则和错误处理。详细阐述Python注释系统,涵盖行内注释、文档字符串和类型注释等多种形式,并提供工业级代码组织方案。研究显示,良好的缩进可提升40%的代码识别速度,降低50%的认知负荷。文章还对比了Sphinx、pdoc等主流文档生成工具,给出企业级项目中的注释编写原则和模板建议,帮助开发者构建更可维护的Python代码。

本博客聚焦 YOLOv11 全流程落地,涵盖架构优化、数据集处理、训练技巧与多场景部署,兼及国产数据库、Java 开发与 AI 模型应用,内容兼顾理论与工程实践,为开发者提供系统干货,助力高效提升技术能力。 1011

深入理解select、poll和epoll及区别

select poll epoll

Dayu_log的博客 720

go实现MQTT broker(附完整源码)

go实现MQTT broker(附完整源码)

希望我的博客,能帮上你解决学习中工作中所遇到的问题 575

时间序列分析(Time Series Analysis) 原理与代码实例讲解

时间序列分析(Time Series Analysis) - 原理与代码实例讲解 作者:禅与计算机程序设计艺术 / Zen and the Art of Computer Programming 关键词:时间序列预测,ARIMA模型,状态空间模型,SARIMA模型,机器学习

AI天才研究院 1247

2.1.1 网络I_O与select、poll、epoll

linux I/O复用select、poll、epoll讲解

Joker1128 213

蓝牙模块HM-10手册

蓝牙模块HM-10手册,该手册对蓝牙模块HM-10进行了详细的介绍和使用方法以及一些AT指令。

高效I/O处理:模型与多路复用的探讨

本文介绍了 I/O 操作的五种主要模型:阻塞 I/O、非阻塞 I/O、同步 I/O、异步 I/O 和信号驱动 I/O,并分析了它们在现代计算机系统中的应用。重点讨论了多路复用技术(如 select、poll 和 epoll)在高并发场景中的重要性及其如何提升 I/O 操作的效率。通过对这些模型和技术的深入理解,开发者能够选择合适的 I/O 方案,以优化应用性能,提升用户体验。

曾经“等你生日那天”都遥远得像未来,如今却可欢愉的挥手说“下个十年见” 11万+

TMS_WebGMaps_1.9.8.0_Full_Source

TMS_WebGMaps_1.9.8.0_Full_Source 全源码 delphi cbuilder

霍尼韦尔SoftMaster使用说明

霍尼韦尔SoftMaster使用说明

Linux IO模式及 select、poll、epoll详解

一 概念说明 在进行解释之前,首先要说明几个概念: 用户空间和内核空间 进程切换 进程的阻塞 文件描述符 缓存 I/O 用户空间与内核空间 现在操作系统都是采用虚拟存储器,那么对32位操作系统而言,它的寻址空间(虚拟存储空间)为4G(2的32次方)。操作系统的核心是内核,独立于普通的应用程序,可以访问受保护的内存空间,也有访问底层硬件设备的所有权限。为了保证用户进程不能直接操作内核(...

王安的博客 2372

C# WinForm 基于DirectShow.dll编写的程序,可边预览边保存视频,音频和图片

基于微软的DirectShow.dll的二次开发1.自动识别连接的摄像头跟麦克风且可以对其进行选择(默认选中第一个)2.可录制wmv和avi两种格式的视频并且都带有音频,avi可以录制的分辨率和帧数进行选择,wmv默认进行了淸晰度优化如不喜欢可去除代码中有相关提示3.可在预览点开之后进行拍照,也可边录制视频边拍照4.添加了视频和音频的压缩功能(酌情使用)这次二次开发发现C#对DirectShow的相关信息太少,这次做完也不敢藏私共享出来,还望大家指正

I/O 多路复用:select、poll、epoll

select和poll是Linux系统中常用的I/O多路复用机制。select通过位操作管理文件描述符,受限于1024的最大数量,使用fd_set结构体数组来跟踪描述符状态。poll则没有数量限制,采用pollfd结构体管理事件,将读写事件合并处理,通过位与运算判断事件发生。两者都提供了高效的I/O监控能力,但poll在可扩展性和使用便利性上更优。示例代码展示了select和poll的基本用法,包括描述符设置和事件检测。

bdn_nbd的博客 838

IO复用函数select poll epoll

select#include <sys/select.h> #include <sys/time.h> int select(int maxfdp1,fd_set *readset,fd_set *writeset,fd_set *exceptset,const struct timeval *timeout)返回值:就绪描述符的数目,超时返回0,出错返回-1 第一个参数maxfdp1指定待测试的描

菜鸡 596

【网络编程开发】11.IO模型 12.IO多路复用

五种IO模型,IO多路复用的三种实现方法

2201_75563094的博客 1293

【Linux】多路转接 Select , Poll和Epoll

参数记录监控最大的文件描述符加1,得到这个参数。用于内部循环数组找到最大文件描述符。这三个参数分别代表读,写和异常监视的文件描述符集合。使用的是fd_set类型表示,用位图来表示文件描述符是否启用。将文件描述符fd添加到集合set中从集合set移除文件描述符fd检查文件描述符fd是否被加入集合set清空集合set中的所有文件描述符 }这是一个指向timeval结构的指针,该结构用于设定select等待 I/O 事件的超时时间。大于0:就绪的文件描述符数量等于0:超时小于0:发生错误。

2401_86449430的博客 3796

多路复用IO ---- select、poll、epoll

select,poll,epoll都是IO多路复用的机制。 (1)select==>时间复杂度O(n) select仅仅知道了有I/O事件发生了,却并不知道是哪那几个流(可能有一个,多个,甚至全部),我们只能无差别轮询所有流,找出能读出数据,或者写入数据的流,对他们进行操作。所以select具有O(n)的无差别轮询复杂度,同时处理的流越多,无差别轮询时间就越长。select适用数组存储流。 (2)poll==>时间复杂度O(n) poll本质上和select没有区别,它将用户传入的数组拷贝到内核

hnujunjie的博客 177

IO多路复用select/poll/epoll

摘要: Linux系统提供了三种I/O多路复用机制:select、poll和epoll。select通过位图监控文件描述符,存在1024连接数限制和O(N)效率问题;poll改用数组结构突破连接限制,但仍需线性扫描。epoll采用事件驱动模型,通过红黑树管理fd,就绪事件O(1)返回,支持ET/LT模式,适合高并发场景。三者中epoll性能最优,但仅限Linux,而select跨平台性最佳。技术演进体现从简单轮询到高效事件通知的优化路径。

LAN_chen_ning的博客 416

linux网络编程-select、poll、epoll

select、poll、epoll是linux下I/O多路转接的三种方式。其中epoll在高并发的服务器中用的比较多。 1. select 函数定义: int select(int nfds,fd_set* readfds,fd_set* writefds,fd_set* exceptfds,strcut timeval* timeout) 函数功能是将要监控的文件描述符集fd_set传入内核,...

littleflypig的博客 621

APUE之I/O多路复用

I/O多路复用有3种具体实现模型:select、poll和epoll /* int select(int nfds, fd_set *readfds, fd_set *writefds,fd_set *exceptfds, struct timeval *timeout) * @nfds 要监听的最大描述符编号加1,select支持的最大描述符编号为FD_SETSIZE(通常是10...

coder 339

select,poll,epoll区别和各自的优缺点

select:        系统提供了select函数来实现多路复用输入/输出模型,它的系统调用是用来让我们的程序监视多个文件句柄的状态变化的。程序会停在select这里等待,直到被监视的文件句柄有一个或者多个发生了状态改变。        0:标准输入        1:标准输出        2:标准错误输出 0,1,2是整数表示的,对应的file*结构的表示就是stdin,std

qingdou_aixuexi的博客 720

一文带你深入了解Linux五种I/O模型和I/O多路复用

本文详细介绍了Linux中的五种I/O模型和I/O多路复用技术。主要内容包括: 五种I/O模型:阻塞I/O、非阻塞I/O、信号驱动I/O、I/O多路复用和异步I/O,分析各自特点和区别 阻塞/非阻塞与同步/异步的概念辨析 I/O多路复用的三种实现方式:select、poll和epoll,比较它们的优缺点 epoll的两种触发模式:水平触发(LT)和边缘触发(ET) 惊群问题及其解决方案 常见面试题总结,包括技术选型建议 文章结构清晰,内容全面,适合准备面试或需要深入理解Linux I/O模型的读者。

铭哥不写bug的博客 454
上一篇: leetcode2022年度刷题分类型总结(十二)并查集
下一篇: 【后端开发面试高频问题】资源总结贴 (查缺补漏专用)
study_&
博客等级 码龄8年 128粉丝 116原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值