为什么epoll比select更高效?

本文章将解决一下几个问题,也是面试常问的问题

1.select和epoll有什么不同?
2.为什么epoll比select高效?
3.epoll永远比select高效吗?


1.select和epoll有什么不同?

<1>select可以监听文件描述符是有限的,由FD_SETSIZE设置,默认是1024,可以通过修改这个宏来增加可监听文件描述符的个数,但资料同时指出这样修改将导致不可预期的效果。

epoll可监听的文件描述符的个数为进程可打开的文件的个数

<2>select中,当有事件就绪时,内核修改参数以通知用户,用户需要遍历所有的fd判断是哪个fd就绪,应用程序索引就绪文件描述符的时间复杂度是O(n),IO效率随着监听的fd的数目增加而线性下降。

epoll中注册了回调函数,当有就绪事件发生的时候,设备驱动程序调用回调函数,将就绪的fd添加到rdllist中,调用epoll_wait时,将rdllist上就绪的fd发送给用户,应用程序索引就绪文件描述符的时间复杂度是O(1),IO效率与fd的数目无关。

<3>epoll支持ET模式,当内核将该事件通知给用户后,用户必须立即处理,这样就减少了可读、可写、异常事件被触发的次数。

select只能工作在相对较低效的LT模式


2.为什么epoll比select高效?

在select中,用户通过fd_set_bits将感兴趣的事件通知内核,内核要将用户感兴趣的事件拷贝到内核空间,并为每个fd分配一个poll_table_page结构体,用来监听该fd上是否有就绪事件。如果有就绪事件,内核修改用户传进来的fd_set_bits告知用户事件有就绪事件发生删除分配的poll_table_page结构体。应用程序要遍历所有的fd找到就绪的fd。因为fd_set_bits已经被内核修改,下次调用select之前必须重置fd_set_bits,然后重新传给内核,内核重新拷贝一份,重新分配结构体

在epoll中,在调用epoll_ctl时,已经将用户感兴趣的事件传给了内核,内核会维持一个内核事件表,记录用户感兴趣的事件,就绪事件发生时,驱动设备调用回调函数将就绪的fd挂到rdllist上。用户调用epoll_wait时,将rdllist上就绪的文件描述符发送给用户。此时发送给用户的都是就绪的fd。


3.不论哪种情况,epoll永远比select高效吗?

不一定!

epoll适用于连接较多,活动数量较少的情况。
(1)epoll为了实现返回就绪的文件描述符,维护了一个红黑树和好多个等待队列,内核开销很大。如果此时监听了很少的文件描述符,底层的开销会得不偿失;

(2)epoll中注册了回调函数,当有时间发生时,服务器设备驱动调用回调函数将就绪的fd挂在rdllist上,如果有很多的活动,同一时间需要调用的回调函数数量太多,服务器压力太大。

select适用于连接较少的情况。
当select上监听的fd数量较少,内核通知用户现在有就绪事件发生,应用程序判断当前是哪个fd就绪所消耗的时间复杂度就会大大减小。

希望我的解释对你有帮助,如有错误,请指正!

  • 4
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值