image.png
然而大多数应用场景中,需要监视的,socket相对固定,并不需要每次都修改。
image.png

epoll的优化措施

  1. 功能分离:进程到等待队列,进程阻塞
  2. 引入了就绪列表rdlist

image.png

epoll的优化措施一:功能分离

select低效的原因之一是将“维护等待队列”和“阻塞进程”两个步骤合二为一
大多数应用场景中,需要监视的socket相对固定,并不需要每次都修改。 :::tips epoll将这两个操作分开,先用epoll_ctl维护等待队列,再调用epoll_wait阻塞进程。 ::: 显而易见的,效率就能得到提升。
image.png

epoll的优化措施二:就绪列表rdlist

select低效的另一个原因在于程序不知道哪些socket收到数据,只能一个个遍历。
如果内核维护一个“就绪列表” rdlist,引用收到数据的socket 就能避免遍历。 :::tips rdlist存储有事件发生的连接 ::: image.png
当socket接收到数据,中断程序做两个工作:

  • 一方面修改rdlist
  • 另一方面唤醒eventpoll 等待队列中的进程,进程A再次进入运行状态。

也因为rdlist 的存在,进程A可以知道哪些socket发生了变化。

epoll三大步骤

image.png

Epoll第一步epoll_create创建

当某个进程调用epoll_create方法时, 内核会创建一个eventpoll对象 (epfd文件描述符),和socket一样,它也会有等待队列。
image.png
image.png

Epoll第二步epoll_ctl注册

  • 可以用epoll_ctl添加或刪除所监听的socket。
  • 如果通过epoll_ctl添加sock1、sock2和sock3的监视,内核会将eventpoll添加到这三个socket的等待队列中

image.png
image.png
image.png
image.png
image.png
当socket收到数据后,中断程序会操作eventpoll的就绪队列rdlist,而不是直接操作读取数据的进程(如果进行A)。当sock2和sock3收到数据后,中断程序让这两个socket进入rdlist。
image.png

Epoll第三 步epoll_wait阻塞

当程序执行到epoll_wait时, 如果rdlist非空则返回, 如果rdlist为空,阻塞进程.
image.png
image.png

当socket接收到数据,中断程序一方面将其插入rdlist, 另一方面唤醒eventpoll等待队列 中的进程,进程A再次进入内核的工作队列。进程A进行运行状态。
image.png
正是因为epoll采用了红黑树的结构,所以能够监听的连接数,可以远远大于1024个
image.png