epoll 的一些使用细节

如果事件 fd 被注册到多个 epoll 中, 事件发生发生时, 每个 epoll 都能触发.

如果注册到 epoll 的 fd 被关闭, 会被自动清除出 epoll, 即不需要 epoll_ctl EPOLL_CTL_DEL.

epoll_wait() 会一直监听 epollhup 事件, 即不需要手工添加 EPOLLHUP events.

为了避免大量 IO 时, ET 模式下 fd 被饿死的情况, Linux 下建议在拥有 fd 的数据结构中增加 ready 位, epoll_wait() 触发事件后仅做置位, 在消费者线程中轮询置位的 fd 列表处理, 即朴素的生产者-消费者模型.

fd 的注册的 events 类型清空之后, 需要 epoll_ctl(epoll_fd, EPOLL_CTL_MOD, fd, &events) 来重设监听 events 类型.

epoll_ctl() 和 epoll_wait() 可以不在一个线程, epoll_ctl() 加入事件之后, epoll_wait() 立即就能知道.

在 LT 模式下, 如果对端 socket 关闭, 会一直触发 EPOLLIN. 如果是 ET 模式, 触发 EPOLLIN, 如果此时处理程序只做了一次 recv, 并根据收到的长度来判断后续处理, 将丢失这一条 socket 关闭事件. 可以在这种情况下尝试多做一次 recv.

epoll_create() 的参数 size, 只要大于 0 即可.

参考文章