关于EPOLL的ET和LT模式的深入理解

epoll也是实现I/O多路复用的一种方法。epoll水平触发(level trigger,LT,LT为epoll的默认工作模式)与边缘触发(edge trigger,ET)两种工作模式。使用脉冲信号来解释LT和ET可能更加贴切。Level是指信号只需要处于水平,就一直会触发;而edge则是指信号为上升沿或者下降沿时触发。

LT:只要内核缓冲区有数据就一直通知,只要socket处于可读状态或可写状态,就会一直返回sockfd;

ET:只有状态发生变化才通知,只有当socket由不可写到可写或由不可读到可读,才会返回其sockfd;

注:(在添加EPOLLIN、EPOLLOUT事件的前提下。)

水平触发

1. 对于读操作

只要缓冲内容不为空,LT模式返回读就绪。

2. 对于写操作

只要缓冲区还不满,LT模式会返回写就绪。

边缘触发

1. 对于读操作

(1)当缓冲区由不可读变为可读的时候,即缓冲区由空变为不空的时候。

(2)当有新数据到达时,即缓冲区中的待读数据变多的时候。

(3)当缓冲区有数据可读,且应用进程对相应的描述符进行EPOLL_CTL_MOD 修改EPOLLIN事件时。

2. 对于写操作

(1)当缓冲区由不可写变为可写时。

(2)当有旧数据被发送走,即缓冲区中的内容变少的时候。

(3)当缓冲区有空间可写,且应用进程对相应的描述符进行EPOLL_CTL_MOD 修改EPOLLOUT事件时。

究竟触发了多少次呢?可以这样想:

(1)当数据量SIZE小于recv函数的接收长度len且小于系统缓冲SO_RCVBUF的时候:ET与LT都触发一次,recv执行一次。

(2)当数据量SIZE大于recv接收长度len但小于系统缓冲SO_RCVBUF的时候:LT触发SIZE/len次,ET触发一次。两者的recv函数执行SIZE/len。(一次ET触发可执行多次recv)

(3)当数据量SIZE大于recv接收长度len且大于系统缓冲SO_RCVBUF的时候:LT触发SIZE/len次,ET触发SIZE/SO_RCVBUF次。两者的recv函数都执行SIZE/len次。(同样一次ET触发执行了多次recv)

显然:

1、ET模式可以显著降低同一个Epoll事件的触发次数。

2、ET模式下同一文件描述符的同类事件有可能多次触发。如:系统读/写缓冲区溢出会分别导致同一个描述符的EPOLLIN/EPOLLOUT事件多次触发。

另外几点要知道:

(1)send和recv函数的len参数是每一次接受或发送的数据量的上限

(2)ET模式下确实每次都终止于EAGAIN。recv的指定的接收长度较小的时候,ET模式下的一次触发会执行多次recv。直到某次recv操作把errno变成了EAGAIN为止。此时errno==EAGAIN条件成立。

(3)这种触发是系统自动完成的。某些程序在errno==EAGAIN的时候,又做了写epoll_ctl配置有点误导人。

(4)两种模式下的recv函数执行的次数都是一样的。

(5)具体执行次数还要考虑缓冲区门限之类的,并非这么简单。

猜你喜欢

转载自blog.csdn.net/mijichui2153/article/details/81120660
今日推荐