select和epoll的区别

127 阅读2分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第9天,点击查看活动详情

使用select函数的多路复用流程

应用进程调用select函数,同时监控多个fd(文件描述符),任何一个数据状态准备就绪就会返回可读状态,这时应用进程再发起recvfrom请求来读取数据

select函数存在如下缺点

  1. 在这个过程中需要将数据从内核空间拷贝到用户空间
  2. 监听的IO最大连接数有限,Linux系统上一般为1024
  3. select响应仅表示有IO事件发生,但不知道是哪个流,需要遍历所有流来找到就绪的fd

image.png poll相较于select的改进:解决了连接数限制的问题,但还是需要遍历流找到就绪的那一个

使用epoll模式的IO多路复用

epoll模式先通过epoll_create()在内核空间创建出红黑树+双向链表的实例,再调用epoll_ctl()向红黑树中添加监听的fd并关联callback,一旦基于某个fd就绪时,内核的回调机制会将fd加入到双向链表中(就绪列表),当进程调用epoll_wait()时,就是从就绪列表中取出就绪fd的过程。

image.png

和poll、select模式的比较

  1. 减少了fd从内核空间和用户空间之间的拷贝的次数:在ctl()方法中每个fd拷贝一次,在wait()方法中阻塞等待不需要拷贝,在处理fd时也只需要从就绪队列中拷贝就绪的fd
  2. 相比select的链表可以监听的更多fd,因为使用了红黑树提高了查询效率
  3. 不需要遍历所有fd判断谁就绪

事件通知机制

是调用wait方法返回通知的机制,有两种模式LT和ET

LT模式:默认的模式,会重复通知多次直到就绪fd都处理完成

ET模式:只会通知1次