select、poll和epoll

本文摘录自《构建高性能Web站点》,详细介绍了select、poll和epoll三种Linux多路I/O就绪通知方法,包括它们的起源、特点、优缺点及使用上的区别。select最早出现于4.2BSD,适用于跨平台,但受限于文件描述符数量;poll则无此限制,但在大量文件描述符情况下开销较大。epoll作为Linux2.6下的实现,几乎具备所有优点,被认为是最具性能的方法,支持水平触发和边缘触发,并能显著减少系统调用时的开销。

转载地址:http://blog.endlesscode.com/2010/03/27/select-poll-epoll-intro/

对select、poll、epoll了解得不多,下面是从《构建高性能Web站点》摘录下来的介绍,等以后真正接触到select、poll和epoll方面的开发再详细写一下使用上的区别。

select

select最早于1983年出现在4.2BSD中,它通过一个select()系统调用来监视多个文件描述符的数组,当select()返回后,该数组中就绪的文件描述符便会被内核修改标志位,使得进程可以获得这些文件描述符从而进行后续的读写操作。

select目前几乎在所有的平台上支持,其良好跨平台支持也是它的一个优点,事实上从现在看来,这也是它所剩不多的优点之一。

select的一个缺点在于单个进程能够监视的文件描述符的数量存在最大限制,在Linux上一般为1024,不过可以通过修改宏定义甚至重新编译内核的方式提升这一限制。

另外,select()所维护的存储大量文件描述符的数据结构,随着文件描述符数量的增大,其复制的开销也线性增长。同时,由于网络响应时间的延迟使得大量TCP连接处于非活跃状态,但调用select()会对所有socket进行一次线性扫描,所以这也浪费了一定的开销。

poll

poll在1986年诞生于System V Release 3,它和select在本质上没有多大差别,但是poll没有最大文件描述符数量的限制。

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

另外,select()和poll()将就绪的文件描述符告诉进程后,如果进程没有对其进行IO操作,那么下次调用select()和poll()的时候将再次报告这些文件描述符,所以它们一般不会丢失就绪的消息,这种方式称为水平触发(Level Triggered)。

epoll

直到Linux2.6才出现了由内核直接支持的实现方法,那就是epoll,它几乎具备了之前所说的一切优点,被公认为Linux2.6下性能最好的多路I/O就绪通知方法。

epoll可以同时支持水平触发和边缘触发(Edge Triggered,只告诉进程哪些文件描述符刚刚变为就绪状态,它只说一遍,如果我们没有采取行动,那么它将不会再次告知,这种方式称为边缘触发),理论上边缘触发的性能要更高一些,但是代码实现相当复杂。

epoll同样只告知那些就绪的文件描述符,而且当我们调用epoll_wait()获得就绪文件描述符时,返回的不是实际的描述符,而是一个代表就绪描述符数量的值,你只需要去epoll指定的一个数组中依次取得相应数量的文件描述符即可,这里也使用了内存映射(mmap)技术,这样便彻底省掉了这些文件描述符在系统调用时复制的开销。

另一个本质的改进在于epoll采用基于事件的就绪通知方式。在select/poll中,进程只有在调用一定的方法后,内核才对所有监视的文件描述符进行扫描,而epoll事先通过epoll_ctl()来注册一个文件描述符,一旦基于某个文件描述符就绪时,内核会采用类似callback的回调机制,迅速激活这个文件描述符,当进程调用epoll_wait()时便得到通知。

### Linux I/O 复用机制:`select`、`poll` `epoll` 的区别比较 #### 一、基本概念 I/O 多路复用是一种允许单个线程同时监视多个文件描述符的技术,以便在任意一个或多个文件描述符变为可读/写时得到通知。Linux 提供了三种主要的 I/O 多路复用机制:`select`、`poll` `epoll`。 --- #### 二、具体特性对比 1. **`select`** - **特点**: - 支持的最大文件描述符数受限于系统常量(通常为 1024)。可以通过重新编译内核调整上限[^3]。 - 每次调用都需要将所有的文件描述符集合从用户空间拷贝到内核空间,并在线性扫描这些文件描述符以判断其是否准备好[^3]。 - 时间复杂度为 O(n),其中 n 表示要监控的文件描述符总数。 - **性能**: - 在少量文件描述符的情况下表现尚可,但在高并发场景下由于需要频繁地复制扫描大量文件描述符,性能下降明显[^3]。 - **典型应用场景**: - 小规模网络应用或者嵌入式设备上的简单通信程序[^3]。 2. **`poll`** - **特点**: - 解决了 `select` 中最大文件描述符数量限制的问题,理论上可以支持无限多的文件描述符。 - 类似于 `select`,仍然存在每次调用都要将所有感兴趣的文件描述符列表传送到内核的空间开销问题[^3]。 - 同样采用轮询方式检测哪些文件描述符已准备就绪,时间复杂度仍为 O(n)[^3]。 - **性能**: - 相较于 `select` 略有改进,但由于底层实现原理相似,在大规模并发情况下依然不够高效[^3]。 - **典型应用场景**: - 较大但非极高的并发环境下的服务器端编程。 3. **`epoll`** - **特点**: - 基于事件驱动模型设计,专门针对高性能需求而优化[^1]。 - 使用红黑树存储注册过的文件描述符及其关联的状态信息;利用双向链表管理活跃的事件队列[^4]。 - 只需一次性的将文件描述符加入到 epoll 实例中即可,后续无需重复传输整个集合至内核层。 - 支持两种触发模式——边缘触发(Edge Triggered, ET)与水平触发(Level Triggered, LT),提供了更大的灵活性[^1]。 - **性能**: - 即使面对海量连接也能维持较高的效率,因为它只会关注那些确实发生了变化的少数几个文件描述符而不是全部检查一遍[^1]。 - 数据结构的设计使得无论是添加还是查询操作都非常迅速,整体时间复杂度接近于 O(1)[^4]。 - **典型应用场景**: - Web 服务、数据库代理等超高并发的服务端架构。 --- #### 三、总结表格 | 属性 | Select | Poll | Epoll | |--------------|---------------------------------|--------------------------------|-------------------------------| | 文件描述符限 | 默认最多 1024 | 无固定限制 | 几乎不受限 | | 效率 | O(n) | O(n) | 接近 O(1) | | 用户态<->内核态交互频率 | 每次都需传递完整集合 | 每次也都需传递完整集合 | 初始化阶段一次性设置 | | 是否支持多种触发模式 | 否 | 否 | 是 | --- #### 四、代码示例 以下是使用 `epoll` 的一段简化版 C++ 示例代码: ```c++ #include <sys/epoll.h> #include <unistd.h> #define MAX_EVENTS 10 int main() { int epoll_fd = epoll_create1(0); if (epoll_fd == -1) { perror("epoll_create1"); return 1; } struct epoll_event event; event.events = EPOLLIN; event.data.fd = STDIN_FILENO; if (epoll_ctl(epoll_fd, EPOLL_CTL_ADD, STDIN_FILENO, &event) == -1) { perror("epoll_ctl: add"); close(epoll_fd); return 1; } struct epoll_event events[MAX_EVENTS]; while (true) { int nfds = epoll_wait(epoll_fd, events, MAX_EVENTS, -1); if (nfds == -1) { perror("epoll_pwait"); break; } for(int i = 0;i < nfds; ++i){ printf("Event on fd %d\n",events[i].data.fd ); } } close(epoll_fd); } ``` --- ###
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值