https://yq.aliyun.com/articles/495842?spm=a2c4e.11153940.0.0.61cf4d40BBz2x2
首先上转帖,这篇文章讲的很透彻了。
ET与LT触发的区别:
红线:fd状态改变是才会触发。那么什么情况会导致fd状态的改变呢?
对于读取操作:
(1) 当buffer由不可读状态变为可读的时候,即由空变为不空的时候。
(2) 当有新数据到达时,即buffer中的待读内容变多的时候。
对于写操作:
(1) 当buffer由不可写变为可写的时候,即由满状态变为不满状态的时候。
(2) 当有旧数据被发送走时,即buffer中待写的内容变少得时候。
蓝线:fd的events中有相应的时间(位置1)即会触发。那么什么情况下会改变events的相应位呢?
对于读操作:
(1) buffer中有数据可读的时候,即buffer不空的时候fd的events的可读为就置1。
对于写操作:
(1) buffer中有空间可写的时候,即buffer不满的时候fd的events的可写位就置1。
说明:红线是时间驱动被动触发,蓝线是函数查询主动触发。
总结一下:
对于ET模式,它的触发方式是转帖链接图中的红线部分,也就是说:
ET下,对于监听读取操作:
(1) 当buffer由不可读状态变为可读的时候,即由空变为不空的时候。
(2) 当有新数据到达时,即buffer中的待读内容变多的时候
(3) 当buffer中有数据可读(即buffer不空)且用户对相应fd进行epoll_mod IN事件时
(1),(2)很好理解,特别对于(3):
EPOLL_CTL_MOD相当于重新修改了该sockfd对应的需要监视的事件,尽管在下一轮中可读数据并未增长,但仍然会提醒该事件发生。
对于写操作:
(1) 当buffer由不可写变为可写的时候,即由满状态变为不满状态的时候。
(2) 当有旧数据被发送走时,即buffer中待写的内容变少得时候。
(3) 当buffer中有可写空间(即buffer不满)且用户对相应fd进行epoll_mod OUT事件时。
其中3与上面一样。
对于LT模式:
ET模式相当于是LT模式的子集,除了上述ET模式的情况外,以下也会进行通知。
这篇转帖写的实在是非常好,值得通读。
另外关于这个TinyWebServer:
有一点小问题:
在向socket中写时:
在遇到写缓冲区满而返回EAGAIN时,返回状态为STATUS_WRITE。
而在主函数中:
它对于STATUS_WRITE的处理却是直接将该sockfd remove掉,也就是说默认了遭遇EAGAIN就相当于已经写完。
这个逻辑是不是有问题,如果说出现:
写缓冲区已满,但写入数据仍为写完的情况,在这个情况下将socket remove掉是不对的,是不是应该不对它remove,而应该等到下次epoll_wait检测到该sockfd可写后继续写入,而又应用层来判断是否写完数据后,return一个success标识,再进行remove才更好呢?
当然,作者是不是考虑到对一个静态页面来说,写缓冲区写满但文件扔未写完的情况不存在呢?