注册 登录  
 加关注
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

小白的博客

嵌入式爱好者

 
 
 

日志

 
 

linux-3.4.2之poll机制分析  

2012-09-12 01:54:57|  分类: 韦东山视频第二轮 |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |
#define SYSCALL_DEFINE3(name, ...)            SYSCALL_DEFINEx(3, _##name, __VA_ARGS__)
#define SYSCALL_DEFINEx(x, sname, ...)       __SYSCALL_DEFINEx(x, sname, __VA_ARGS__)
#define __SYSCALL_DEFINEx(x, name, ...)     asmlinkage long sys##name(__SC_DECL##x(__VA_ARGS__))

所以:
SYSCALL_DEFINE3(poll, struct pollfd __user *, ufds, unsigned int, nfds , int, timeout_msecs)
就相当于:
asmlinkage long sys_poll( poll, struct pollfd __user *, ufds, unsigned int, nfds , int, timeout_msecs)

在用户空间执行poll函数的时候,会调用系统函数sys_poll,也就是SYSCALL_DEFINE3,于是我们开始内核分析:
SYSCALL_DEFINE3(poll, struct pollfd __user *, ufds, unsigned int, nfds , int, timeout_msecs)
    //设置超时时间
    poll_select_set_timeout(to, timeout_msecs / MSEC_PER_SEC, NSEC_PER_MSEC * (timeout_msecs % MSEC_PER_SEC));
    do_sys_poll(ufds, nfds, to);
         poll_initwait(&table);
         init_poll_funcptr(&pwq->pt, __pollwait);
             //也就是说:pwq->pt->_qproc=__pollwait,__pollwait用于将当前进程加入等待队列
             //__pollwait函数在我们注册的poll函数里面会调用
              pt->_qproc = qproc;
         do_poll(nfds, head, &table, end_time);

我们贴出do_poll的部分内核代码:
static int do_poll(unsigned int nfds,  struct poll_list *list, struct poll_wqueues *wait, struct timespec *end_time)
{
for (;;) {
struct poll_list *walk;

for (walk = list; walk != NULL; walk = walk->next) {
struct pollfd * pfd, * pfd_end;

pfd = walk->entries;
pfd_end = pfd + walk->len;
                       //这个循环是针对多个进程的
for (; pfd != pfd_end; pfd++) {
                                //这个函数就是调用我们在驱动里面实现的poll函数,我们下面会贴出部分代码
                               //只要有一个进程的返回值不为0,count就不为0
if (do_pollfd(pfd, pt)) {
count++;
pt->_qproc = NULL;
}
}
}

pt->_qproc = NULL;
if (!count) {
count = wait->error;
if (signal_pending(current))
count = -EINTR;
}
                //一旦count不为0或者超时就会跳出循环,也就是应用程序返回了
if (count || timed_out)
break;

if (end_time && !to) {
expire = timespec_to_ktime(*end_time);
to = &expire;
}
                //如过count仍是0的话,就会在这里休眠一段时间,然后再次循环
if (!poll_schedule_timeout(wait, TASK_INTERRUPTIBLE, to, slack))
timed_out = 1;
}
return count;
}

static inline unsigned int do_pollfd(struct pollfd *pollfd, poll_table *pwait)
{
unsigned int mask;

mask = file->f_op->poll(file, pwait);//这就是调用我们注册的poll函数
//如果mask 与pollfd->events相同就能保证mask不为0
mask &= pollfd->events | POLLERR | POLLHUP; 

return mask;
}

下面我们总结一下poll机制:
在用户空间调用poll函数,然后会跳转进内核;之后会指向我们注册的poll函数,在poll函数里面我们会放一条指令:poll_wait,poll_wait里面会调用__pollwait函数将当前进程放入等待队列,但是这是并没有休眠,只是加入队列;如果没有发生我们想要的事件的话,我们要使返回值为0,这时就会进入休眠状态;一旦发生了我们想要的时间的话,我们可以唤醒进程!比如我们下一节要写的按键驱动程序,如果发生了按键按下,就会在中断函数里面唤醒进程!
  评论这张
 
阅读(2799)| 评论(0)
推荐 转载

历史上的今天

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2017