I/O多路复用之水平触发和边沿触发模式

多路I/O复用不管是select,poll还是epoll,其都是通过同时监听多个文件描述符,当有文件文件描述符处于就绪状态时,触发通知。

LT(Level Trigger,水平触发)模式和ET(Edge Trigger,边沿触发)模式是两种文件描述符准备就绪的通知模式。

水平触发通知:如果文件描述符上可以非阻塞地执行I/O系统调用,此时认为它已经就绪,触发通知。
边沿触发通知:如果文件描述符自上次状态检查以来有了新的I/O活动(比如新的输入),此时需要触发通知。

(1)当采用水平触发通知时,我们可以在任意时刻检查文件描述符的就绪状态。这表示当我们确定了文件描述符处于就绪状态时(比如存在有输入数据),就可以对其执行一些I/O操作,然后重复检查文件描述符,看看是否仍然处于就绪态(比如还有更多的输入数据),此时我们就能执行更多的I/O。举个例子,比如说我们采用epoll水平触发模式监听一个文件描述符的可读,当这个文件可读就绪时,epoll会触发一个通知,然后我们执行一次读取操作,但这次操作我们并没有把该文件描述符的数据全部读取完。当下一次调用epoll监听该文件描述符时,epoll还会再次触发通知,直到该事件被处理完。这就意味着,当epoll触发通知后,我们可以不立即处理该事件,当下次调用epoll监听时,然后会再次向应用程序通告此事件,此时我们再处理也不晚。
(2)与之相反的是,当我们采用边沿触发时,只有当I/O事件发生时我们才会收到通知。还是上个例子,如果这次我们采用epoll的边沿触发模式监听一个文件描述符的可读,当可读就绪时,epoll会触发一个通知,如果我们此时不立即处理该事件,当下次再调用epoll监听时,虽然该文件描述符的状态是可读的,但是此时epoll并不会再给应用程序发送通知。因为在边沿触发工作模式下,只有下一个新的I/O事件到来时,才会再次发送通知。另外,当文件描述符收到I/O事件通知时,通常我们并不知道要处理多少I/O(例如有多少字节可读)。因此,采用边沿触发通知程序通常要按照如下规则来设计。

  • 在接收到一个I/O事件通知后,程序在某个时刻应该在相应的文件描述符上尽可能多地执行I/O(比如尽可能多地读取字节)。如果程序没这么做,那么就可能失去执行I/O的机会。因为直到产生另一个I/O事件为止,在此之前程序都不会再接收到通知了,因此也就不知道此时应该执行I/O操作。
  • 如果程序采用循环来对文件描述符执行尽可能多的I/O,而文件描述符又被设置为可阻塞的,那么最终当没有更多的I/O可执行时,I/O系统调用就会阻塞。基于这个原因,每个被检查的文件描述符通常应该置为非阻塞模式,在得到I/O事件通知后重复执行I/O操作,直到相应的系统调用(比如read(),write())以错误码EAGAIN或EWOULDBLOCK的形式失败。

可见,ET模式在很大程度上降低了同一个epoll事件被重复触发的次数,因此效率要比LT模式高。

下表是I/O多路复用select,poll和epoll所支持的通知模型:

I/O模式水平触发边沿触发
select()支持不支持
poll()支持不支持
epoll()支持支持

select和poll只支持LT工作模式,epoll的默认的工作模式是LT模式。当往epoll内核事件表中注册一个文件描述符上的EPOLLET事件时,epoll将以ET模式来操作该文件描述符。关于epoll如何使用ET模式,我们在这里就不再详细介绍了。我会在后面介绍epoll的博文中详细介绍epoll的LT模式和ET模式的使用。

推荐文章:I/O多路复用之epoll

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值