系统调用
系统调用
Linux多路复用
poll & select & epoll
| 特性 | select | poll | epoll |
|---|---|---|---|
| 出现时间 | 最早(BSD) | 后来(POSIX 标准) | Linux 2.6(现代) |
| 监听方式 | 位图(fd_set) | 数组(pollfd) | 内核事件表(epoll实例) |
| fd 上限 | 1024(默认) | 无限制 | 无限制 |
| 事件通知机制 | 轮询(O(n)) | 轮询(O(n)) | 回调 + 事件驱动(O(1)) |
| 返回事件方式 | 遍历全部 fd | 遍历全部 fd | 直接返回活跃 fd |
| 内核拷贝 | 每次都拷贝 fd 集 | 每次都拷贝 | 注册一次,共享内核态 |
| 性能随连接数变化 | 严重下降 | 严重下降 | 基本恒定 |
| 使用复杂度 | 简单 | 中等 | 稍复杂(epoll_ctl / epoll_wait) |
| 是否支持边缘触发 | 否 | 否 | ✅ 支持(EPOLLET) |
select
最早的多路复用机制,
1 | |
传入fd集合,最多1024个,select返回fd可以读写的,调用返回后需要遍历检查fd中是否有事件
缺点:1.最多1024个链接;2.需要全量复制fd集合;3.需要遍历fd;4.返回后的集合会被修改。
poll
1 | |
去除了fd集合数量的上限,改用stuct pollfd数组代替位图。
缺点:1.仍然需要复制全量fd数组进内核;2.仍要遍历全量fd
epoll
1 | |
异步回调,把fd注册进内核,只在事件发生时通知应用程序。
- 当某个 fd 可读/可写时,内核会把它放入就绪队列;
- 调用
epoll_wait时,直接返回就绪 fd 列表; - 不需要像
select/poll那样遍历所有 fd。
💡 所以 epoll 的性能是 O(1):无论监听几万个 fd,
触发模式
| 模式 | 含义 | 使用场景 |
|---|---|---|
| 水平触发(Level Trigger,LT) | 只要缓冲区有数据就会通知 | 默认模式,兼容性好 |
| 边缘触发(Edge Trigger,ET) | 只在状态变化时通知一次 | 性能更高,必须非阻塞 I/O |
系统调用
https://yicizhang00.github.io/posts/基础理论/操作系统/Linux/系统调用/