IO多路复用(select、poll、epoll)
一直都对IO多路复用搞不清楚,写篇文章将所看到的内容记录一下,防止遗忘。
IO多路复用
IO多路复用就是使用内核机制来轮询一组文件描述符,监视这写fd是否有IO事件发生,如果有IO发生程序会被告之。
IO 多路复用的方式主要有 select、poll、epoll,这三个函数都会进行阻塞,所以可以放在 while(true)循环里使用,不会造成 CPU 的空转
select
select()系统调用提供了一种实现同步多路复用的机制
select 只有一个函数,调用 select 时,需要将监听句柄和最大等待时间作为参数传递进去,select 会发生阻塞,直到一个事件发生了,或者等到最大 1 秒钟(tv 定义了这个时间长度)就返回。
select方法的参数
-
读文件描述符集合、写文件描述符集合、异常描述符集合、超时时间
-
一般更关心文件读操作,所以其他位置可以置为null,第二个参数一般是引用一个bitmap用来代表哪些文件描述符是被监听的。
select源码
源码中比较重要的就是main部分,上半部分主要做了两件事:
-
创建socket客户端
-
创建了5个文件描述符,并把这五个文件描述符放入了数组中。
select函数的执行流程:
-
select是阻塞函数,当没有数据时,会一直阻塞在select那一行。
-
当有数据时将rset中对应的那一位置为1
-
select函数返回,不再阻塞
-
遍历文件描述符数组,判断哪个fd被置位了。
-
读取数据,然后处理
select函数的缺点:
-
bitmap默认大小为1024,虽然可以调整,但还是有限度的。
-
rset每次循环都必须重新置位为0,不可重复使用。
-
尽管将rset从用户态拷贝到内核态,由内核态判断是否有数据,但是还是有拷贝的开销。
-
当有数据时select就会返回,但是select函数并不知道哪个文件描述符有数据了,后面还需要再次对文件描述符数组进行遍历。效率比较低。
poll
与select()不同,它具有低效的三个基于位掩码的文件描述符集,poll()使用单个nfds pollfd结构数据。原型更简单:
poll的参数:
-
自定义的结构体数组
-
数组的长度
-
超时时间
pollfd 结构对事件和返回事件有不同的字段,因此不需要每次都创建它
-
fd: 文件描述符
-
events:在意的事件是什么,如果在于读就是pollin,如果在意写就是pollout
-
revents:对events的回馈,开始时为0,当有数据可读时就置为pollin,类似于select的rset
将上面示例更改为使用poll:
就像对 select 所做的那样,我们需要检查每个 pollfd 对象以查看其文件描述符是否已准备好,但不需要每次迭代都构建集合
poll的执行流程:
-
将5个fd从用户态拷贝到内核态
-
poll为阻塞方法,执行poll方法,如果有数据会将fd对应的revents置位pollin
-
poll方法返回
-
循环遍历,查找哪个fd被置位为pollin了
-
将revents重新位置0,便于复用
-
对置位的fd进行读取和处理
相比于select解决了bitmap大小限制问题和rset不可重用的情况。
epoll
Epoll系统调用在内核中创建和管理上下文。将任务分为 3 个步骤:
-
使用 epoll_create 在内核中创建上下文
-
使用 epoll_ctl 在上下文中添加和删除文件描述符
-
使用 epoll_wait 等待上下文中的事件
将上面的代码示例改为epoll
epoll的执行流程:
-
当有数据的时候,会把相应的文件描述符"置位",但是epoll没有revent标志位,所以并不是真正的置位。这时候会把有数据的文件描述符放到队首。
-
epoll会返回有数据的文件描述符的个数
-
根据返回的个数 读取前N个文件描述即可
-
读取、 处理
Epoll 、select 和 poll
-
可以在等待时添加和删除文件描述符
-
epoll_wait 仅返回具有就绪文件描述符的对象
-
epoll 具有更好的性能 O(1) 而不是 O(n)
-
epoll 可以表现为水平触发或边缘触发
-
epoll 是特定于 Linux 的,因此不可移植
__EOF__

本文链接:https://www.cnblogs.com/youngerwb/p/16157917.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角【推荐】一下。您的鼓励是博主的最大动力!
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?