OS IO多路复用
I/O 多路复用技术 : 只用一个进程来维护多个 Socket
select/poll
select 实现多路复用的方式 :
- 将已连接 Socket 都放在文件描述符集合
- 调用 select(), 将文件描述符集合拷到内核
- 内核遍历文件描述符集合, 检查网络事件
- 当有事件,就将该 Socket 标为可读或可写
- 将整个文件描述符集合拷回用户态
- 用户态遍历找可读或可写的 Socket, 对处理
总结 :
- 要遍历 2 次文件描述符集合 (内核态, 用户态)
- 拷贝 2 次文件描述符集合 (用户到内核, 内核到用户)
poll/select区别 :
- select 用固定长度的 BitsMap 组织文件描述符集合, 受 FD_SETSIZE 限制, 默认最大值: 1024
- poll 用动态数组,以链表组织, 只受系统文件描述符限制
- poll/select 无本质区别, 随着并发数越多,性能越低
epoll
epoll :
- 红黑树 (O(logn)) 组织所有待检测文件描述字
- 用事件驱动机制, 当某个 socket 事件发生,内核将该事件加到就绪事件列表(链表)
事件触发模式 :
- 边缘触发 (edge-triggered, ET): 事件发生, epoll_wait 苏醒一次, 要一次性将内核缓冲区数据读完
- 水平触发 (level-triggered, LT): 事件发生, epoll_wait 不断苏醒, 直到 read 读完才结束
ET/LT 对比 :
- 边缘触发模式一般和非阻塞 I/O 使用
- 一般边缘触发比水平触发效率高, 边缘触发能减少 epoll_wait 调用数
- select/poll 只能水平触发
- epoll 默认: 水平触发, 能配边缘触发