使用epoll的边沿触发(EPOLLET)模式时,程序如果收到一次可读通知只读一小段数据就返回,可能出现缓冲区里明明还有数据、后面却迟迟没有新通知的情况。理解ET与LT的区别,是写稳定事件循环的关键。
epoll_wait() → 处理就绪fd → 非阻塞读写 → 回到事件循环

LT与ET的差别
只要文件描述符仍然处于就绪状态,后续等待通常还会继续报告。编程较直观,但可能产生重复通知。
更关注状态变化。若一次通知后没有把当前可处理的数据读完,缓冲区仍有数据时未必会再产生新的边沿通知。
ET模式的常见写法
for (;;) {
ssize_t n = read(fd, buf, sizeof(buf));
if (n > 0) {
handle_data(buf, (size_t)n);
continue;
}
if (n == 0) {
close_peer(fd); // 对端关闭
break;
}
if (errno == EINTR) continue;
if (errno == EAGAIN || errno == EWOULDBLOCK) break;
handle_io_error(fd, errno);
break;
}上面的逻辑假设fd已经设为非阻塞。读到EAGAIN/EWOULDBLOCK,意味着当前没有更多数据可立即读取;对于ET模式,这通常是结束本轮读取的正确边界。监听socket的accept循环也要考虑把已排队连接取到EAGAIN。
还要处理这些边界
读返回0:对端关闭连接,不要把它当作“暂时没数据”。
errno为EINTR:按系统调用语义重试。
EPOLLERR、EPOLLHUP:不能只处理EPOLLIN/EPOLLOUT。
写事件:只在确实有待发送数据时关注可写,避免一直监听EPOLLOUT造成忙循环。
面试参考答法
ET模式要把文件描述符设为非阻塞,并在收到就绪通知后循环读写,直到返回EAGAIN或EWOULDBLOCK,或连接关闭、发生错误。否则缓冲区里还留有数据时,程序可能等不到新的边沿通知。LT更容易上手,但两种模式都要正确处理关闭、错误和缓冲区状态。

扫码关注






























