epoll机制总结

看了一周的linux epoll源代码做一个总结。

epoll源代码在eventpoll.c里。首先是调用epoll_create,内部调用sys_epoll_create,这个函数主要给epoll分配文件描述符fd和文件结构体struct file,并实现file、fd、epoll私有数据结构eventpoll的绑定,主要的函数是ep_alloc和anon_inode_getfd,ep_alloc初始化eventpoll结构体的各种队列和epoll的红黑树,这个红黑树用来ll_ctl内部调用sys_epoll_ctl,首先根据epoll文件描述符的参数获取struct file,然后这个函数最复杂最重要的部分是ep_insert,这个函数参数分别是eventpoll结构体,要添加的事件event,要添加的文件描述符和对应的file结构体。首先分配epitem内存并初始化它的各种队列。有几个比较重要的函数init_poll_funcptr(&epq.pt, ep_ptable_queue_proc);revents = tfile->f_op->poll(tfile, &epq.pt);前一个函数是向epq.pt绑定一个回调函数,后一个函数是直接调用待添加文件的poll函数,在poll函数内部会回调epq.pt即ep_ptable_queue_proc。ep_ptable_queue_proc函数有如下几个参数:目标文件的file,目标文件的等待队列和这个函数本身的函数指针,新建一个wait_queue_t进行相关赋值设置回调函数最后把这个结构体插入到目标文件的等待队列。当网络有事件到来有数据(收到数据会出发以下函数tcp_v4_rcv->......->wake_up_interruptible_all->最后wake_up_all)会回调等待队列的回调函数,回调函数会把这个epitem插入到eventpoll的已完成队列中并唤醒epoll_wait。epoll_wait内部调用sys_epoll_wait,内部调用ep_poll。首先判断eventpoll结构体的已完成等待队列是否有已经完成的任务,如果就创建一个wait_queue存放当前进程得信息和回调函数并加入到eventpoll的wq队列中,如果所要监听的有数据就回调ep_ptable_queue_proc函数中已经注册的函数,这个函数内部回调eventpoll的wq队列的回调函数进而唤醒epoll_wait判断来的事件是不是所要监听的事件如果是就把这个事件通过ep_send_events函数拷贝到用户空间并返回。

接下来说下epoll内部常用的几个队列。epoll的eventpoll结构体最重要的一个队列是rdllist,这个队列指向有消息的队列,ep->wq被epoll_wait等候的队列ep->rb,红黑树用于保存epitem,红黑树可以加快查找速度,ep->rb根据被检测目标文件epitem的struct file和fd来进行红黑树比较插入,当有事件发生时,epi->rdllink被插入到ep->rdllist,当有事件到来时候,会把epoll_wait阻塞的进程进行唤醒,根据rdllist里面的结构体找到对应的epitem,根据对应的epitem找到被监控文件的file并执行poll再一次确认得到消息event

你可能感兴趣的:(epoll)