参考书目:《Linux高性能服务器编程》-游双著
LT:电平触发
ET:边沿触发
将一个事件的发生理解为状态的转变,理解为从0到1的转变。
例如:EPOLLIN读就绪事件的发生条件:内核接收缓存区中的字节数 >= 低水位标记SO_RCVLOWAT。故
-
将(内核接收缓存区中的字节数 < 低水位标记SO_RCVLOWAT)视为0
-
将(内核接收缓存区中的字节数 >= 低水位标记SO_RCVLOWAT)视为1
则,LT的触发方式为:只要处于1就触发,ET的触发方式为:0-1的一次跳变才会触发一次
这就带来了LT和ET使用方式上的区别:
-
对于采用LT模式的文件描述符,当 epoll_wait 检测到其上有事件发生并将此事件通知应用程序后,应用程序可以不立即处理该事件。因为若不处理该事件,应用程序下次调用 epoll_wait 时, epoll_wait 还会再次向应用程序通告该事件,直到该事件被处理。
-
对于采用ET模式的文件描述符,当 epoll_wait 检测到其上有事件发生并将此事件通知应用程序后,后续的 epoll_wait调用将不再向应用程序通知这一事件(这种事件)。故当 epoll_wait 通知应用程序有事件发生时,应用程序必须立即处理(处理完)该事件。
例如:
- 当 epoll_wait 检测到一次EPOLLIN(可读事件,说明接收缓存区中的字节数大于等于低水位标记了),处于LT模式下时,调用一次recv就行了,不用管读缓存中的数据是否完全读出。LT模式下,只要接收缓存区中的字节数大于低水位标记,则一直处于“1”状态,则下次 epoll_wait 调用依然会通知应用程序此事件。
- 当 epol_wait 检测到一次 EPOLLIN(可读事件,说明接受缓存区中的字节数大于等于低水位标记了一次),处于ET模式下时,必须循环使用非阻塞地recv来接收数据(确保缓存区中的数据被完全读出)。若此次没有完全读出数据,如果读缓存中剩余的数据量大于低水位标记,则后面的 epoll_wait 永远也不会通告EPOLLIN事件了,因为再也没有“从0到1的跳变”。(默认水位标记都是1字节,故一般只有读完和没读完两种状态)