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

本文详细介绍了三种I/O多路复用技术:select、poll及epoll的工作原理和特性。select和poll采用水平触发模式,每次调用都需要传递描述符列表;epoll则通过内核事件表实现高效管理,支持边缘触发模式,显著提高了处理大量并发连接的能力。

select 和poll的区别:

select:

select的触发方式是水平触发(LT),应用程序如果没有完成对一个已经就绪的文件描述符进行IO操作,那么之后每次select调用还是会将这些文件描述符通知进程。

创建数组,保存描述符

(一次while要做的事:)

  1. 清空集合FD_ZERO
  2. 遍历数组,将fd写入fdset集合中(由于内核对fd_set的修改,应用程序下次调用select前需要重置fd_set集合。),循环次数由描述符个数决定
  3. 将fdset集合传给select(系统调用)---->从用户空间向内核空间拷贝(select需要复制大量的句柄数据结构,产生巨大的开销);
  4. 内核实现是轮询方式(一个一个检查,检测那些事件就绪),将其中就绪的描述符返回给应用程序,检测就绪事件的算法的时间复杂度为o(n),描述符越多,耗时越长,性能越差
  5. select返回后,需遍历所有描述符,找到就绪的描述符(FD_ISSET)

相比select模型,poll使用链表保存文件描述符,因此没有了监视文件数量的限制

poll:

 poll通过把文件描述符和事件定义在pollfd中,任何事件都被统一处理,从而使得编程接口简洁许多。并且内核每次修改的是pollfd结构体的revents成员,而events成员保持不变,因此下次调用poll时无须重置pollfd结构体类型的事件集参数。

  1. 不需要每次清空数组,只要需要动态维护住即可
  2. 将数组传给Poll(系统调用)---->从用户空间向内核空间拷贝
  3. 内核实现是轮询方式(一个一个检查),将其中就绪的描述符返回给应用程序,检测就绪事件的算法的时间复杂度为o(n),描述符越长,耗时越长
  4. Poll返回后,需遍历所有描述符,找到就绪的fd

selec poll都只能在相对低效的LT模式,而epoll可以工作在ET高校模式

select和poll都没有从本质上解决,当描述符数量过多时,效率越低的情况

epoll:

     创建一个内核事件表, 把用户关心的文件描述符上的事件都放在内核里的事件表中,从而无须像select,poll那样每次调用都要重复传入文件描述或事件集,但epoll需要使用一个额外的文件描述符,来唯一标识内核中创建的这个内核事件表。

select、poll、epoll区别:

### 异步IO多路复用selectpollepoll区别 #### Select机制分析 Select采用的是轮询的方式去检测每一个文件描述符的状态变化,当调用`select()`时,它会阻塞直到有一个或多个文件描述符准备好进行读取或写入操作,或者是超时发生。然而,在每次调用之前都需要重新设置感兴趣的文件描述符集合,并且对于大量连接来说效率较低,因为其内部实现是对所有传入的文件描述符依次做线性扫描。 #### Poll机制解析 PollSelect相似之处在于两者都基于水平触发模式工作,这意味着只要某个文件描述符处于可读状态,则一直保持激活直至被消费掉为止。但是poll解决了select的最大文件描述符数量受限于FD_SETSIZE的问题,理论上支持更大的并发量。不过poll同样存在性能瓶颈—随着监控列表的增长,遍历整个数组查找已准备好的事件仍然是一项耗时的工作[^4]。 #### Epoll特性介绍 Epoll则采用了完全不同的设计理念来优化上述两种方式存在的缺陷: - **边缘触发(Edge Triggered, ET) vs 水平触发(Level Triggered, LT)**: 支持这两种模式,默认情况下为LT模式下运作。ET模式仅在监测到新的数据到来瞬间触发一次回调通知给应用层;而在LT模式里只要有未处理的数据就会持续报告。 - **高效的通知机制**: 不同于前两者的被动查询模型,epoll主动告知哪些具体的socket已经发生了特定类型的活动,从而使得开发者能够精准定位并响应感兴趣的变化源而不必逐一排查全部可能的对象。 - **高性能扩展能力**: 利用了Linux内核提供的红黑树结构以及hash表技术实现了高效的动态增删改查功能,这不仅提高了系统的吞吐率还降低了CPU占用率。此外,由于只关心活跃链接所以即使面对海量级的同时在线用户也能维持良好的表现力[^1]。 ```c int epoll_fd = epoll_create(EPOLL_SIZE); struct epoll_event event; event.events = EPOLLIN | EPOLLET; // 设置为边沿触发 event.data.fd = listen_sock; // 注册监听套接字至epoll实例中 if (epoll_ctl(epoll_fd, EPOLL_CTL_ADD, listen_sock, &event) == -1){ perror("epoll set insertion error"); } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值