持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第9天,点击查看活动详情
使用select函数的多路复用流程
应用进程调用select函数,同时监控多个fd(文件描述符),任何一个数据状态准备就绪就会返回可读状态,这时应用进程再发起recvfrom请求来读取数据
select函数存在如下缺点
- 在这个过程中需要将数据从内核空间拷贝到用户空间
- 监听的IO最大连接数有限,Linux系统上一般为1024
- select响应仅表示有IO事件发生,但不知道是哪个流,需要遍历所有流来找到就绪的fd
poll相较于select的改进:解决了连接数限制的问题,但还是需要遍历流找到就绪的那一个
使用epoll模式的IO多路复用
epoll模式先通过epoll_create()
在内核空间创建出红黑树+双向链表的实例,再调用epoll_ctl()
向红黑树中添加监听的fd并关联callback,一旦基于某个fd就绪时,内核的回调机制会将fd加入到双向链表中(就绪列表),当进程调用epoll_wait()
时,就是从就绪列表中取出就绪fd的过程。
和poll、select模式的比较
- 减少了fd从内核空间和用户空间之间的拷贝的次数:在ctl()方法中每个fd拷贝一次,在wait()方法中阻塞等待不需要拷贝,在处理fd时也只需要从就绪队列中拷贝就绪的fd
- 相比select的链表可以监听的更多fd,因为使用了红黑树提高了查询效率
- 不需要遍历所有fd判断谁就绪
事件通知机制
是调用wait方法返回通知的机制,有两种模式LT和ET
LT模式:默认的模式,会重复通知多次直到就绪fd都处理完成
ET模式:只会通知1次