I/O 多路复用
I/O 多路复用让一个线程等待多个描述符的就绪事件,适合大量连接、每条连接大部分时间都在等待的服务。Linux 常用 select、poll 和 epoll。
1. 面试核心
先记住这几条,再读正文- 多路复用解决等待多个 I/O 对象的问题,不自动提供业务并行。
- poll 每次传入关注集合,epoll 维护关注集合并返回就绪事件。
- 边缘触发通常配合非阻塞 I/O,持续处理到 EAGAIN。
2. 关注集合与就绪结果
select 和 poll 每次调用都传入待检查的描述符集合。epoll 通过 epoll_ctl 维护关注集合,通过 epoll_wait 获得就绪事件,避免应用每次提交完整集合。
注册监听 socket
等待就绪事件
监听 socket 可读:接受连接
客户端可读:读取、缓冲、解析
客户端可写:继续发送未完成字节
epoll 的优势常出现在连接多但每次就绪比例低的场景。就绪事件交付、网络读取和业务处理仍然有成本,不能把整体性能概括成“epoll 一律 O(1)”。
3. 水平触发与边缘触发
水平触发在描述符持续满足就绪条件时仍会报告。边缘触发关注状态变化;若读了一部分就停止,缓冲区还剩数据,却可能没有新的变化触发下一次通知。
因此边缘触发通常使用非阻塞描述符,并循环 read,直到暂不可用 EAGAIN。为了避免单连接长期占用线程,还需要调度公平性;若设处理预算后暂停,要确保应用能主动继续处理剩余数据。
4. 使用边界
一次可读事件可能对应数据、EOF 或错误,返回事件不代表得到完整请求。持续订阅可写事件也可能导致忙循环,因为多数空闲 socket 通常可写;一般只在还有待发送数据时关注它。
事件循环应把长计算与可能长时间阻塞的操作移到适当的工作线程,并限制排队容量。连接数量、活跃比例、每次处理量和下游耗时决定最终吞吐与延迟。
5 · 面试题卡片
先想答案,再翻面题目来自公开面经。点任意一张进入翻卡,可左右切换,看完回到这里。
逐张翻看 1 张 →5.1 epoll 和 poll 有什么区别,使用边缘触发时为什么通常要读到 EAGAIN?
出现公司:字节跳动
考察重点:关注集合的管理、边缘触发语义与非阻塞读取循环。
参考回答
poll 每次传入并检查关注集合,epoll 把关注集合保留在内核,通过等待接口返回就绪事件。边缘触发依赖就绪状态变化,若没有处理完已有数据就等待,可能不再收到新的变化通知。非阻塞读取循环处理到 EAGAIN,才能确认当前已无可读数据,同时还要安排连接之间的公平调度。