C/C++ Select Poll Epoll 多路转接

多路转接:

  • 并发性​:单线程/进程即可同时处理多个I/O操作,无需创建大量线程或进程

  • ​非阻塞​:在监听过程中,程序不会阻塞,仅在检测到就绪事件时才触发处理

  • ​事件驱动​ :基于文件描述符的就绪状态(如可读、可写、异常)执行回调或轮询操作

    用个通俗易懂的例子举例:一个人钓鱼,掌管着多个鱼竿,哪个鱼竿的浮漂动,才会去拉起钓竿。

多路转接----select与poll与epoll

一.select

1.参数

select可以同时管理和监听多个文件描述符,程序会停在select函数,直到有就绪事件。

nfds----鉴定文件描述符中最大值+1 如 1 4 7三个描述符 nfds应为8

readfds/writefds/exceptfds----确定关心哪些文件描述符的哪些事件--读 写 异常

timeval----

1. NULL--阻塞等待

​​适用场景​​:需持续监控I/O事件,无超时需求。

2. ​​0-非阻塞等待
select立即返回,仅检查当前描述符状态(轮询模式)

​​适用场景​​:高频检测I/O状态,避免程序阻塞。

3. 指定数字 ​​超时模式​​(timeout > 0
在指定时间内等待事件就绪,超时后返回0。例如,设置超时为3秒:

fd_set可以认为是一个bit位图,通过在第几个bit位置确定是哪个文件描述,因此他的大小是有限制的,取决于fd_set,这与内核系统的设置有关。

如readfds 0001101 //就是关心 0,2,3文件描述符的读事件。

然后假如说0文件描述符的读事件就绪,那么select就会返回

原来的0001101会被修改为0000001,其他没就绪的就被置空。

但是对位操作比较麻烦,所以为我们提供了接口。

2.返回值

1.执行成功则返回文件描述词状态已改变的个数

  1. 如果返回0代表在描述词状态改变前已超过timeout时间。

3.当有错误发生时则返回-1,错误原因存于errno,此时参数readfds,writefds, exceptfds 和 timeout 的值变成不可预测。

3.总结

缺点:

1.需要自己手动管理文件描述符,在循环监听时,每次都需要手动设置fd集合。

2.每次使用fd集合都需要将其从用户态拷贝到内核态

3.select每次监听,都需要在内核态进行遍历所有fd

4.select能监听的fd有限。

二.Poll

poll与select比较相似。

1.参数

fds---

就相当于将select的readfds/writefds 整合起来。

一个pollfd 中包含了,需要监听文件描述符,与需要监听的事件,和返回就绪事件。

nfds---fds数组的数量

2.返回值

3.总结

缺点:

1.每次内核需要轮询检测哪些事件就绪

2.每次使用fd集合都需要将其从用户态拷贝到内核态

3.随着监听fd的增多,每次可能只有几个fd就绪,效率会随着下降。

优点:

1.不需要在循环设置监听事件,接口使用更方便

2.没有监听事件数量设置(但过多,性能也下降)

三.epoll

1.函数与参数

int epoll_create(int size);

返回一个epoll句柄,size可填可不填,记住如果不需要epoll模型,要close()关闭

作用:在内核创建一个epoll模型

何为epoll模型

简单的概括来说

一个epoll模型中有一个红黑树和一个链表

红黑树有将fd和event封装起来的结点epollitem,每次插入删除通过红黑树进行,所以效率非常的高,其次当事件就绪,与其对应的驱动程序会调用epollitem相应的回调函数,将其加入链表中,

那么链表就可以存储就绪事件

int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event);

epfd句柄

op操作符

fd需要监听的文件描述符

event这里我们只需要关心events和data.fd与fd设置一样即可 即可

events:

ET模式:文件描述符状态变化​

例如读事件从有无数据到有数据 类似电平0到1跳转的那一瞬间才会触发

例如写事件缓冲区空间从无到有 类似电平从1到0跳转的那一瞬间

所以我们必须要一次性将数据读完,

所以应文件描述符设置非阻塞模式,这是因为read阻塞式读取一次可能不会将数据读完,所以我们应采用非阻塞轮询的方式,直到所有数据读完。

LT模式:持续通知

例如只要有数据,就一直在就读队列, 类似电平只要为1就为真。

epoll默认为LT模式。

若是我们想设置ET模式

只需要 事件 | 模式即可

cpp 复制代码
ev.events = EPOLLIN | EPOLLET;

int epoll_wait(int epfd, struct epoll_event * events, int maxevents, int timeout);

epfd句柄

events传入要监听的events,epoll会将就绪事件赋值到events数据中

maxevnets是events结构体数组的元素个数

timeout与上述epoll相似

返回值与poll一样

2.优点

1.使用方便,不需要每次再循环设置监听事件,实现输入输出参数分离

2.数据拷贝轻量,只需要add时候加入文件标识符的时候需要拷贝(而其他两个每次循环都要进行拷贝)

3.事件回调机制,当一个事件就绪,不需要循环遍历,只需要调用回调函数,将当前结点直接加入就绪队列。

4.没有文件限制

相关推荐
tianyuanwo1 天前
深入解析 RISC-V 虚拟化中的 UEFI 固件配置:从 XML 到 NVRAM 的生命周期管理
xml·linux·risc-v
牛油果子哥q1 天前
并查集(DSU)超精讲,路径压缩、按秩合并、万能模板、连通性判定、最小生成树与刷题实战全解
数据结构·c++·最小生成树·并查集
小冷爱读书1 天前
allocator
开发语言·c++
森G1 天前
71、打包发布---------打包发布
c++·qt
小冷爱读书1 天前
C++ 单例四种实现完整演进逻辑
开发语言·c++·c++学习
道川贤林1 天前
OrangePi 系统启动优先级修改
linux·linux驱动·orangepi·u-boot
xsc-xyc1 天前
用 Tailscale + Syncthing 实现手机、电脑与 NAS 的跨网络文件同步
linux·网络·网络安全·智能手机·电脑
sdm0704271 天前
多路转接-select
网络·c++·select·多路转接
beethobe1 天前
PythonQt 学习之旅(一):从零构建 C++ 与 Python 的桥梁
c++·python·学习
鹏易灵1 天前
C++——2.常量与 const、constexpr 初识详解
java·开发语言·c++