epoll分析
来源:互联网 发布:淘宝优惠软件是真的吗 编辑:程序博客网 时间:2024/05/16 09:17
ep_insert这个函数开始分析 里面调用了
init_poll_funcptr(&epq.pt,ep_ptable_queue_proc);
init_poll_funcptr这个函数就一句
static inline voidinit_poll_funcptr(poll_table *pt, poll_queue_proc qproc)
{
pt->qproc= qproc;
}
也就是将ep_ptable_queue_proc这个函数指针赋值给(&epq.pt)->qproc
revents = tfile->f_op->poll(tfile,&epq.pt);将调用pipe_poll(以pipe为例)
pipe_poll(struct file *filp, poll_table*wait)里面有poll_wait(filp, &pipe->wait, wait);这一句
poll_wait里面
static inline void poll_wait(struct file *filp, wait_queue_head_t * wait_address, poll_table *p)
{
if(p && wait_address)
p->qproc(filp,wait_address, p); #1
}
参数p就是之前epoll里的&epq.pt,p->qproc也就是ep_ptable_queue_proc
第二个参数wait_address就是&pipe->wait,这个pipe的wait是什么呢我们可以看一下
struct pipe_inode_info *alloc_pipe_info(struct inode *inode)
{
structpipe_inode_info *pipe;
pipe= kzalloc(sizeof(struct pipe_inode_info), GFP_KERNEL);
if(pipe) {
init_waitqueue_head(&pipe->wait);
pipe->r_counter= pipe->w_counter = 1;
pipe->inode= inode;
}
returnpipe;
}
init_waitqueue_head该函数初始化一个已经存在的等待队列头,它将整个队列设置为"未上锁"状态,并将链表指针prev和next指向它自身。也就是初始化&pipe->wait这个等待队列头的指针。
我们再回过头来看#1这个地方,也就变成了ep_ptable_queue_proc(filp, &pipe->wait, &epq.pt)
static void ep_ptable_queue_proc(structfile *file, wait_queue_head_t *whead,
poll_table *pt)
{
structepitem *epi = ep_item_from_epqueue(pt);
structeppoll_entry *pwq;
if(epi->nwait >= 0 && (pwq = kmem_cache_alloc(pwq_cache,GFP_KERNEL))) {
init_waitqueue_func_entry(&pwq->wait,ep_poll_callback);
pwq->whead= whead;
pwq->base= epi;
add_wait_queue(whead,&pwq->wait);
list_add_tail(&pwq->llink,&epi->pwqlist);
epi->nwait++;
}else {
/*We have to signal that an error occurred */
epi->nwait= -1;
}
}
struct epitem *epi =ep_item_from_epqueue(pt);是通过&epq.pt找到其从属的epitem对象。
pwq = kmem_cache_alloc(pwq_cache,GFP_KERNEL)); alloc一个
/* Wait structure used by the poll hooks */
struct eppoll_entry {
/*List header used to link this structure to the "struct epitem" */
structlist_head llink;
/*The "base" pointer is set to the container "struct epitem"*/
void*base;
/*
* Wait queue item that will be linked to thetarget file wait
* queue head.
*/
wait_queue_twait;
/*The wait queue head that linked the "wait" wait queue item */
wait_queue_head_t*whead;
};
init_waitqueue_func_entry(&pwq->wait, ep_poll_callback);将回调函数ep_poll_callback注册给了&pwq->wait(等待项,这个等待项会被连入到pipe等待队列中)的func项,当
&pipe->wait 被赋值给了pwq->whead
add_wait_queue(whead, &pwq->wait);将等待项连接到&pipe->wait等待队列头中
至此pipe_poll完成了
pipe_write的时候会wake_up_interruptible_sync(&pipe->wait);调用关系如下
wake_up_interruptible_sync(&pipe->wait);
->__wake_up_sync((x),TASK_INTERRUPTIBLE,1)
->__wake_up_sync(wait_queue_head_t*q, unsigned int mode, int nr_exclusive)
->__wake_up_common(q,mode, nr_exclusive, sync, NULL);
static void__wake_up_common(wait_queue_head_t *q, unsigned int mode,
int nr_exclusive, int sync, void *key)
{
wait_queue_t *curr, *next;
list_for_each_entry_safe(curr, next,&q->task_list, task_list) {
unsigned flags =curr->flags;
if (curr->func(curr, mode,sync, key) &&
(flags& WQ_FLAG_EXCLUSIVE) && !--nr_exclusive)
break;
}
}
这个curr->func就是之前的&pwq->wait 的func也就是ep_poll_callback,他依次调用pipe等待队列上的各个等待项对应的callback函数
回调函数在调用时会再执行pipe_poll函数,来明确是不是指定的关注事件发生,若成立则将 epitem插入到eventpoll中的rdlist,并激活在epoll fd上wait的进程,并将事件回传至用户态.这样就能实现对目标fd的事件监听.(to be continued…)
- epoll分析
- epoll 分析
- poll epoll 分析
- EPOLL源码分析
- epoll源码分析
- (转)epoll源码分析
- epoll 内核分析
- epoll源码结构分析
- epoll源码分析
- epoll源码分析
- epoll源码实现分析
- epoll源码分析(一)
- epoll源码分析(二)
- epoll源码分析(三)
- epoll源码分析
- epoll源码实现分析
- epoll源码实现分析
- epoll实现分析
- 详解UML中的6大关系(关联、依赖、聚合、组合、泛化、实现)
- poj 2464 Brownie Points II
- Dom4j里Xpath使用介绍
- PHP上传文件类型
- Qt 的启动界面上添加进度条
- epoll分析
- 鸟哥的Linux私房菜:基础学习篇
- C# 窗体间传值总结
- Fedora16 Firefox 安装applet 插件
- 利用adb查看模拟器中的数据库
- JBoss Seam与Apache DeltaSpike的未来
- Observers and Dispatching Events
- 参数 - 学习笔记
- FPGA 按键防抖动,最精简的写法只有10行