谈谈select/poll/epoll的事件触发方式

事件触发模式

epoll 的事件触发模式分为边缘触发(edge-triggered,ET)和水平触发(level-triggered,LT)。

边缘触发模式

当被监控的 Socket 描述符上有可读事件发生时,服务器端只会从 epoll_wait 中苏醒一次,即使进程没有调用 read 函数从内核读取数据,也依然只苏醒一次,因此我们程序要保证一次性将内核缓冲区的数据读取完,在收到通知后应尽可能地读写数据,以免错失读写的机会。因此,会循环从文件描述符读写数据,那么如果文件描述符是阻塞的,没有数据可读写时,进程会阻塞在读写函数那里,程序就没办法继续往下执行。所以,边缘触发模式一般和非阻塞 I/O搭配使用,程序会一直执行 I/O 操作,直到系统调用(如 read 和 write)返回错误,错误类型为 EAGAIN 或 EWOULDBLOCK。
优点:每次内核只通知一次,大大减少了内核资源的浪费,提高了效率。
缺点:不能保证数据的完整性,即不能确保及时取出所有的数据。

水平触发模式

当被监控的 Socket 上有可读事件发生时,服务器端不断不断地从 epoll_wait 中苏醒,直到内核缓冲区数据被 read 函数读完才结束,目的是告诉我们有数据需要读取。
优点:保证了数据的完整输出,即只要还有数据在缓冲区中,epoll_wait就会一直被触发,直到缓冲区为空。
缺点:当数据较大时,需要不断从用户态和内核态切换,消耗大量的系统资源,影响服务器性能。

注意

  • select/poll 只有水平触发模式,epoll 默认的触发模式是水平触发,但是可以根据应用场景设置为边缘触发模式。一般来说,边缘触发的效率比水平触发的效率要高,因为边缘触发可以减少 epoll_wait 的系统调用次数,系统调用也是有一定的开销的的(存在上下文的切换)。但是两种模式各有利弊。另外,使用 I/O 多路复用时,最好搭配非阻塞 I/O 一起使用。

muduo使用的是LT,主要原因如下:

  • 不会丢失数据或者消息:应用没有读完内核会不断地上报;
  • 低延迟处理:每次读数据只需要一次系统调用,照顾了多个连接的公平性,不会因为某个连接上的数据量过大而影响其他的连接处理消息;
  • 跨平台处理:像select一样可以跨平台使用。
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值