跳转至

epoll的实现机制

总图

epoll

accept创建新的socket

process

初始化socket对象

accept_init_socket

为新的socket申请file

accept_init_file

接收连接,添加新文件到当前打开文件列表中

epoll_accpet

epoll_create的实现

创建eventpoll

create_eventpoll

关联到当前进程的打开文件列表中

eventpoll_process

epoll_ctl

这里以添加为例:
在使用 epoll_ctl 注册每一个 socket 的时候,内核会做如下三件事情
1. 分配一个红黑树节点对象 epitem
2. 添加等待事件到 socket 的等待队列中,其回调函数是 ep_poll_callback
3. 将 epitem 插入到 epoll 对象的红黑树里

初始化epitem

对于每一个 socket,调用 epoll_ctl 的时候,都会为之分配一个 epitem
init_epitem

设置socket等待队列

init_epollwaitqueue

将epitem插入到红黑树中

epitem_insert_in_rbt

epoll_wait

  • 判断就绪队列中是否有就绪事件
  • 假设确实没有就绪的连接,定义等待事件,并把 current (当前进程)添加到 waitqueue 上
  • 添加到等待队列
  • 当前线程主动让出CPU进入睡眠状态,选择下一个进程调度

epoll_wait

data come

data_come

接收数据到等待队列

accept_data_in_acceptQueue

查找就绪队列中的回调函数

check_readyQueue_callback

执行回调函数

run_callback

执行socket就绪通知

run_ready_notice


总结

  1. epoll_create创建eventpoll
  2. epoll_ctl(添加)添加socket创建epitem插入到红黑树中
  3. epoll_wait检查就绪队列中是否有就绪事件,如果没有则将当前线程添加到等待队列中并主动让出CPU进入睡眠
  4. 数据包到达网卡,软中断执行接收数据到接收队列(socket)
  5. 插入epoll就绪队列
  6. 检查是否有线程阻塞
  7. 唤醒用户线程,返回事件