epoll为什么如此高效

本文参考epoll源码分析文档:https://www.nowcoder.com/discuss/26226

edge-triggered VS level-triggered

在我的博文《Linux的select poll epoll的IO多路复用》中介绍过:
level-triggered即条件触发,只要满足事件的条件,比如有数据需要读,就一直不断地把这个事件传递给用户;
edge-triggered即边缘触发,只有第一次满足条件的时候才触发,之后就不会再传递同样的事件了。一般来说边缘触发的效率比条件触发的效率要高。
从上文的博文中可以看出,在 ep_send_events_proc 函数的最后,针对 level-triggered 情况,当前的 epoll_item 对象被重新加到 eventpoll 的就绪列表中,这样在下一次 epoll_wait 调用时,这些 epoll_item 对象就会被重新处理。又由于,在最终拷贝到用户空间有效事件列表中之前,会调用对应文件的 poll 方法,以确定这个事件是不是依然有效。所以,如果用户空间程序已经处理掉该事件,就不会被再次通知,但是会导致epoll_wait空跑一次;如果没有处理,意味着该事件依然有效,就会被再次通知。
这就是为什么我们说edge-triggered效率会高一些。

epoll VS poll/select

1、poll/select 先将要监听的 fd 从用户空间拷贝到内核空间, 然后在内核空间里面进行处理之后,再拷贝给用户空间。这里就涉及到内核空间申请内存,释放内存等等过程,这在大量 fd 情况下,是非常耗时的。而 epoll 维护了一个红黑树,通过对这棵黑红树进行操作,可以避免大量的内存申请和释放的操作,而且查找速度非常快。
2、select/poll 从休眠中被唤醒时(某个描述符发生事件,时间片到,发生信号),内核就会遍历内部的 list 去检查到底是哪一个事件到达,并没有像 epoll 一样, 通过 fd 直接关联 eventpoll 对象,快速地把 fd 直接加入到 eventpoll 的就绪列表中。
3、poll/select返回时,需要遍历fd集合,以查找哪些fd上面有事件发生,而epoll直接返回有事件的集合。

epoll出发时机

补充一下epoll事件的触发时机
1.水平触发的时机
对于读操作,只要缓冲内容不为空,LT模式返回读就绪;
对于写操作,只要缓冲区还不满,LT模式会返回写就绪。
2.边缘触发的时机
对于读操作
当缓冲区由不可读变为可读的时候,即缓冲区由空变为不空的时候;
当有新数据到达时,即缓冲区中的待读数据变多的时候;
当缓冲区有数据可读,且应用进程对相应的描述符进行EPOLL_CTL_MOD 修改EPOLLIN事件时。
对于写操作
当缓冲区由不可写变为可写时;
当有旧数据被发送走,即缓冲区中的内容变少的时候;
当缓冲区有空间可写,且应用进程对相应的描述符进行EPOLL_CTL_MOD 修改EPOLLOUT事件时。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值