一句话定义
select 是 Linux 系统中最早出现的 I/O 多路复用机制,它允许单个进程同时监控多个文件描述符的状态变化。内核通过 线性扫描(Linear Scan) 位图集合的方式检查描述符的就绪状态,并在至少一个描述符就绪时返回。
核心原理
select 的运作机制可以概括为“位图注册 + 全量轮询”:
- 位图注册:用户程序将想要监控的 FD 放入一个固定长度(默认 1024)的位图(fd_set)中,并将其从用户态拷贝到内核态。
- 内核轮询:内核会遍历这个位图,检查每个 FD 的状态。如果有 FD 就绪,内核会标记该位图并返回。
- 用户态检查:程序收到返回后,必须再次遍历整个位图,通过
FD_ISSET宏来找出到底是哪个 FD 准备好了。
为什么它有 1024 的限制?这是因为
fd_set在内核中是一个固定大小的数组。虽然可以通过修改内核源码来扩大,但由于其 O(n) 的遍历效率,FD 越多性能下降越快,因此 1024 逐渐成为了一个历史性的“硬伤”。
为什么每次调用都要重新初始化?内核在返回时会直接修改传入的位图(覆盖掉未就绪的位),因此
select是“不可复用”的,下次调用前必须重新设置。
应用场景
- 老旧系统兼容:在一些非常古老的 Unix 系统或对性能要求极低的简单工具中仍在使用。
- 跨平台开发:由于其出现最早,几乎所有的操作系统(包括 Windows)都支持
select。
知识扩展
- fd_set:
select使用的底层位图数据结构。