epoll —— Linux 高性能 I/O 多路复用详解
epoll(详解)
epoll 是 Linux 提供的高性能 I/O
多路复用机制,适合在大量并发连接场景下使用。相比传统的
select/poll,epoll
将被监控的描述符注册在内核中,内核维护就绪列表并通过事件通知用户态,从而实现更低的开销和更好的扩展性。
核心对比:select / poll / epoll
| 机制 | 工作方式 | fd数量限制 | 性能 | 注释 |
|---|---|---|---|---|
| select | 每次传入全部 fd 并遍历 | 1024(默认) | O(n) | 需要复制 fd 集合到内核 |
| poll | 传入结构体数组并遍历 | 无限制 | O(n) | 避免了 fd 集合位图限制 |
| epoll | fd 在内核注册,事件触发时返回 | 无限制 | O(1) 摘要 | 内核维护就绪链表,减少遍历开销 |
epoll 的核心数据结构
- 红黑树:存储所有已注册(监控)的 fd
- ready list(就绪链表):内核记录已经就绪的 fd,epoll_wait 从该链表返回事件
- 回调/事件:用户通过
epoll_ctl指定事件类型(例如EPOLLIN/EPOLLOUT)
三个主要系统调用
epoll_create1(flags):创建 epoll 实例(推荐使用epoll_create1(0))epoll_ctl(epfd, op, fd, &event):向 epoll 实例添加 / 修改 / 删除 fdepoll_wait(epfd, events, maxevents, timeout):等待并返回就绪事件列表
LT(Level-Triggered) vs ET(Edge-Triggered)
| 模式 | 含义 | 特点 |
|---|---|---|
| LT | 水平触发 | 默认模式,只要缓冲区有数据,每次 epoll_wait 都会返回该
fd |
| ET | 边缘触发 | 仅在状态变化时通知一次,需要用户配合非阻塞 I/O 并循环读取直到
EAGAIN |
ET
模式适合高并发且追求更低系统调用次数的场景,但对程序要求更高:必须将 fd
设为非阻塞,并在收到一次事件后循环读/写直到返回
EAGAIN。否则可能出现“遗漏”数据的情况。
Reactor 模式与 epoll 的结合
Reactor 模式由三部分组成:Event Loop(事件循环)、Dispatcher(事件分发)、Handler(事件处理)。epoll 常被用作底层的事件分发机制:
- Event Loop:调用
epoll_wait获取就绪事件 - Dispatcher:将就绪事件派发给对应的 Handler(如读写处理函数)
- Handler:执行具体的 I/O 读写与业务逻辑