1. epoll_create
1. 此系统调用分配了eventpoll数据结构, 并初始化了其中wq和poll_wq两个waiting queue
2. 创建了匿名inode节点, 此inode的file_operaitons 即eventpoll_fops仅仅提供了release, poll 两个方法
2. epoll_ctl
1. 由输入的epoll_fd 得到对应的file结构, epoll_fd当然属于进程的了。
2. 由fd得到需要poll的那个file,即tfile
3. 由file->private_data得到第一步中分配的eventpoll结构
4. 分配一个epItem, 初始话此item,item->ep即指向那个eventpoll结构,item->event为epll_ctl系统调用传入的需要监听的event
5. 在栈里面定义一个ep_pqueue 结构,epq.epi = item.
6. 并将ep_ptable_queue_proc函数指针付给此ep_pqueue对象, 即 ep_pqueue.pt.qproc = ep_ptable_queue_proc
7. 调用tfile->f_op->poll函数,将上面的ep_pqueue.pt函数传入
8. 上面的f_op对应到sock即为sock_poll函数
9. 而sock_poll函数呢,其实又是调用sock->ops->poll函数
10. 对应到tcp sock,即tcp_poll函数了
11. tcp_poll函数呢, 调用sock_poll_wait函数转而调用poll_wait函数,并上面的参数传入
12. 而poll_wait调用函数执行ep_ptable_queue_proc函数,来挂载waitqueue了, 其参数为socket的sk_sleep, 类型为waiting_queue_head
13. ep_ptable_queue_proc函数则分配一个eppoll_entry结构,其中包含了wait这个wait_queue成员
并使用函数指针ep_poll_callback来初始化这个wait, 即 eppoll_entry->wait.func= ep_poll_callback
然后呢, 将eppoll_entry->wait挂载到sk_sleep这个wait queue 头上面去了。
14. waitqueue 挂好了, 并且回调函数也初始化好了。
3. epoll_wait
1. 根据传入的epoll_fd得到对应的file指针,进而得到eventpoll对象
2. 调用ep_poll函数, 此函数呢, 创建了一个wait queue对象 wait
3. 将这个wait对象挂载eventpoll->wq上面去。
4. 然后开始等,判断eventpoll对象的rdlist是否为空, 不空, 就可以返回了。
4. 何时调用
1. 当tcp上面有数据ready的时候, 函数ep_poll_callback会被调用。
2. ep_poll_callback函数呢,调用waitqueue_active(&ep->wq)来唤醒3.4的等待啦。
1. 此系统调用分配了eventpoll数据结构, 并初始化了其中wq和poll_wq两个waiting queue
2. 创建了匿名inode节点, 此inode的file_operaitons 即eventpoll_fops仅仅提供了release, poll 两个方法
2. epoll_ctl
1. 由输入的epoll_fd 得到对应的file结构, epoll_fd当然属于进程的了。
2. 由fd得到需要poll的那个file,即tfile
3. 由file->private_data得到第一步中分配的eventpoll结构
4. 分配一个epItem, 初始话此item,item->ep即指向那个eventpoll结构,item->event为epll_ctl系统调用传入的需要监听的event
5. 在栈里面定义一个ep_pqueue 结构,epq.epi = item.
6. 并将ep_ptable_queue_proc函数指针付给此ep_pqueue对象, 即 ep_pqueue.pt.qproc = ep_ptable_queue_proc
7. 调用tfile->f_op->poll函数,将上面的ep_pqueue.pt函数传入
8. 上面的f_op对应到sock即为sock_poll函数
9. 而sock_poll函数呢,其实又是调用sock->ops->poll函数
10. 对应到tcp sock,即tcp_poll函数了
11. tcp_poll函数呢, 调用sock_poll_wait函数转而调用poll_wait函数,并上面的参数传入
12. 而poll_wait调用函数执行ep_ptable_queue_proc函数,来挂载waitqueue了, 其参数为socket的sk_sleep, 类型为waiting_queue_head
13. ep_ptable_queue_proc函数则分配一个eppoll_entry结构,其中包含了wait这个wait_queue成员
并使用函数指针ep_poll_callback来初始化这个wait, 即 eppoll_entry->wait.func= ep_poll_callback
然后呢, 将eppoll_entry->wait挂载到sk_sleep这个wait queue 头上面去了。
14. waitqueue 挂好了, 并且回调函数也初始化好了。
3. epoll_wait
1. 根据传入的epoll_fd得到对应的file指针,进而得到eventpoll对象
2. 调用ep_poll函数, 此函数呢, 创建了一个wait queue对象 wait
3. 将这个wait对象挂载eventpoll->wq上面去。
4. 然后开始等,判断eventpoll对象的rdlist是否为空, 不空, 就可以返回了。
4. 何时调用
1. 当tcp上面有数据ready的时候, 函数ep_poll_callback会被调用。
2. ep_poll_callback函数呢,调用waitqueue_active(&ep->wq)来唤醒3.4的等待啦。
5. 总结:
1. 关键是2层wait 和 wakeup
2. 当tcp socket ready的时候, 会进行回调。
3. 回调的时候, 激活epoll上面的wait,然后返回。