select、poll、epoll三组I/O复用的比较

         这三组系统调用都能同时监听多个文件描述符。他们将等待由timeout参数指定的超时时间,直到一个或者多个文件描述符上有事件发生时返回,返回值是文件描述符的数量。返回0代表没有事件发生。下面我们从事件集、最大文件描述符、工作模式以及具体实现等四个方面比较他们的异同。

          这三组函数都通过某种结构体变量 来告诉内核监听那些事件描述符上的事件,并使用该结构体类型参数来获取内核处理的结果。select的参数类型fd_set没有将文件描述符和事件绑定, 它仅仅是一个文件描述符集合,因此select需要提供三个这种类型的参数来分别传入和输出可读、可写以及异常等事件。这一方面使得select不能处理更多类型的事件, 另一方面由于内核对fd_set集合的在线修改,应用程序在下次调用select前不得不重置这三个fd_set集合。poll的参数类型pollfd把文件描述符和事件都定义在其中,任何事件都被统一处理,这使得编程接口简洁得多。并且内核每次修改pollfd中的revents成员,而events不发生改变,因此下次调用的时候不需要再传入用户感兴趣的事件。

由于每次select和poll都返回整个用户注册的事件集合(包括就绪的文件描述符和未就绪的文件描述符),所以应用程序索引就绪文件的时间复杂度为O(N),epoll则采用了另一个接口epoll_ctl来控制往其中添加、删除、修改事件。这样,每次epoll_wait调用都从内核事件表中获取用户注册的事件。而无须反复从用户空间读入这些事件。epoll_wait系统调用的events参数仅用来返回就绪的事件,这使得应用程序在索引就绪文件描述符的时间复杂度为O(1)

        poll和epoll_wait分别用nfds和maxevents参数指定内核最多监听的文件描述符和事件。这两个数值都能达到系统允许打开的最大文件描述符数目,即65535。而select 允许监听的最大文件描述符个数通常是有限的,虽然用户可以修改这个限制,但可能会导致不可预期的后果。

       select和poll都只能工作在相对低效的LT模式下,而epoll则可以工作在ET高效模式下。而且epoll还支持EPOLLONESHOT事件。 该事件能进一步减少可读、可写和异常事件被触发的次数。

     从实现原理上来讲,select和epoll采用的都是轮询的方式,即每次调用都要扫描整个注册的文件描述符集合,并将其中就绪的文件描述符返回给用户程序,因此他们检测就绪事件的算法的时间复杂度是O(N),epoll_wait则不同,它采用的是回调的方式。内核检测到就绪的文件描述符时, 将触发回调函数,回调函数就将该文件描述符上对应的事件插入内核就绪事件队列。内核最后在适当的时机将该事件队列返回给用户,因此epoll_wait不用检测整个文件描述符集合其算法复杂度为O(1),但是,当链接比较多,epoll_wait的效率未必比select、poll的效率高,因为回调函数被触发的太过于频繁,所以epoll_wait适用于链接比较多,但是活动链接比较少的情况下。

 下图是三组I/O复用的总结

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值