epoll ET与LT模式

LT模式:水平触发,epoll的默认模式,只要有数据可读或者有空间可写epoll_wait()函数就会返回。(对于一次事件,若没有处理完,epoll_wait会一直通知,直到事件处理完毕)

ET模式:边缘触发,有读事件或写事件到来才会触发epoll_wait()函数返回,换言之,当有一次读事件触发epoll_wait函数返回后,不论你这次数据有没有读完,之后并不会触发epoll_wait函数,除非有新的读事件到来。(对于一次事件,epoll_wait只会通知一次,无论你有没有处理完毕)

设置ET模式的方法:只要对events位或一个EPOLLET就行

event.events |= EPOLLET;

ET模式的注意事项:
1.对于读写的connfd 边缘触发模式下我们最好使用非阻塞IO+轮询的方式一次性将数据处理完,因为当我们使用边缘触发+阻塞IO的时候,由于epoll_wait只会通知一次,若我们一次读不完数据,且一直没有新的读事件发生,则剩下的数据永远无法获得,若我们使用轮询的方式来处理这种情况,则会阻塞在最后一次IO上,这样将会造成其他IO请求饥饿现象。
2.对于监听的sockfd 边缘触发模式下,对于accept我们应当使用非阻塞+轮询的方式。考虑以下场景,同时有多个连接请求到达,服务器TCP就绪队列瞬间累积多个就绪,但我们采用的是ET模式,epoll_wait只会通知一次,也就是只能处理一个连接请求,其他请求无法得到处理,所以我们一次accept就应该把就绪队列里的请求处理完,所以应该采用非阻塞+轮询的方式,当accept返回-1且errno==EAGAIN时表示连接请求处理完成。
3.这个就不只是针对epoll的ET模式了,当我们使用多路IO转接时(select,poll,epoll),accept应当工作在非阻塞模式下。考虑以下场景当我们有一个连接请求,当程序处于select返回与accept调用之间时,客户端主动发送 RST 终止连接,若accept工作在阻塞模式下,则程序会阻塞在该处直到有新的连接请求,在这段时间内所有的fd都得不到处理。所以我们应当让accept工作在非阻塞模式下。

发布了31 篇原创文章 · 获赞 4 · 访问量 943

猜你喜欢

转载自blog.csdn.net/qq_39781096/article/details/104774823