POLL/EPOLL的实现剖析

参考自:http://blog.csdn.net/21aspnet/article/details/2627662?reload#reply 里面有源码的详细剖析。


POLL实现剖析:


sys_poll()首先设置关键数据结构struct poll_wqueues中的回调函数poll_wait(用来将current加入到每个fd对应的等待队列中)。接着kmalloc()获得存储pollfd结构数组的空间(通常是一页poll_list包含若干pollfd),讲用户pollfd数组复制到内核空间(瓶颈一:参数传递和页分配)。


接着调用do_poll()循环检测fd事件就绪标志,直到有fd就绪,超时或者信号到来。第一次循环将current加入到所有fd相关等待队列中(除非超时为0),检测是否退出循环(fd事件就绪标志,直到有fd就绪,超时或者信号到来),否则等待(设置超时时间,当传给poll的timeout为-1时,这里是永久等待)再继续循环。后面的循环负责检测事件的就绪标志,不再重复将current加入到等待队列中。


上面的具体调用过程是:do_poll() 对每一poll_list调用 do_pollfd() ,后者对每一fd调用 file->f_op->poll() ,file->f_op->poll()检测事件标志并可能通过上面设置的回调函数把current加入到待队列中(传入的回调函数为NULL则不处理,对应上面的第二次及以后的循环)。(瓶颈二:需要遍历查看是否有就绪描述符


回调函数poll_wait()具体是为每个fd初始化struct poll_table_entry结构,同过此结构中的wait字段将current加入到等待队列中。


以下是struct poll_wqueues table 相关结构。(poll_table_page和poll_table_entry是包含关系)


    


EPOLL实现剖析:

为了避免上述的瓶颈一:参数传递和页分配,epoll采取在内核空间保留参数的方法,具体是采取红黑树结构来添加/删除/修改操作的epoll描述符事件(通过epoll_ctl())。

为了避免上述的瓶颈二:需要遍历查看是否有就绪描述符,采取唤醒回调机制,即当事件就绪时自动回调函数将事件添加到就绪链表中并唤醒进程,事件驱动模型。而不是进程再去遍历查看描述符就绪事件。


具体剖析如下:

epoll采取了文件系统接口,这也体现了UNIX一切皆文件的特点。所以epoll以模块的形式注册eventepollfs特殊文件系统,另外创建两个slab告诉缓存: struct epitem(红黑树元素) struct  eppoll_entry(用于事件等待,类似poll的poll_table_entry)

sys_epoll_create(int size): 创建一个新的epoll,创建相应的file和inode,创建新的struct eventpoll并把地址

赋给file->private_data。

sys_epoll_ctl(int epfd, int op, int fd, struct epoll_event __user *event):

从红黑树中(eventpoll的rb_root是红黑树的根)添加/删除/修改操作的epoll描述符事件。

sys_epoll_wait(int epfd, struct epoll_event __user *events, int maxevents, int timeout):

循环检测就绪链表(eventpoll的rdlist)是否为空,如果不为空,超时到达或者信号到来,则返回,否则睡眠直到超时到达或有检测事件发生,继续循环。


核心的唤醒回调是通过调用epoll_ctl插入元素的时候,通过init_waitqueue_func_entry(&pwq->wait, ep_poll_callback);设置了唤醒回调函数,该函数ep_poll_callback在事件到达时执行,将对应的描述符epi加入到就绪链表rdlist中。


 

对于ET边缘触发的处理,是sys_epoll_wait后半部分处理的,具体处理分下面三个函数:

ep_collect_ready_items(ep, &txlist, maxevents):将ep的rdlist中的元素移到txlist中。

ep_send_events(ep, &txlist, events):调用file->f_op->poll()检测事件,如果关注事件到来则向用户空间参数写入事件信息,即写入epoll_event数组。

ep_reinject_items(ep, &txlist):如果描述符没有设置EPOLLET且事件是就绪的,那么将该描述符对应的epi就绪加入到就绪链表rdlist中。

如果设置了ET,那么用户缓存就绪信息,即高速模式。



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值