linux下的poll机制,poll机制分析

上一次用中断来实现按键驱动程序里面,如果我们一直没有按键按下触发中断应用程序会一直的在休眠,现在我们想让它隔一段时间就返回一个值要怎么做呢,这就是POLL机制,我们可以用poll机制来实现它,下面来分析一下这个poll机制:

我们知道当我们应用程序open,write..时,驱动程序里面也会有相应的open,write等函数(其实是产生了一个软中断,swi异常处理函数指针被组织成了一个表格,swi指令机器码的位[23:0]被用来索引,这样通过不同的swi

index指令就可以调用不同的swi异常处理函数,它们被称为系统调用,比如sys_open,sys_read,sys_poll等);那poll也是一样的,当我们应用程序poll时,驱动程序也会有一个poll,那我们现在就从sys_poll入手来分析poll机制是怎样的;

应用程序:poll

内核:sys_poll

do_sys_poll(.....,struct timespec *end_time)

poll_initwait(&table);

init_poll_funcptr(&pwq->pt,

__pollwait);>(table->qproc =

__pollwait)pt->qproc = qproc;

do_poll(nfds, head, &table,

end_time);

for (;;)

{

for (; pfd != pfd_end; pfd++) {

if (do_pollfd(pfd, pt)) {>mask =

file->f_op->poll(file, pwait);

//驱动poll

mask = poll_wait(file, &button_waitq, wait)

mask = __pollwait (filp,&button_waitq, p);

//把当前进程挂到button_waitq队列中

count++;//如果返回mask非0count++

pt = NULL;

//break条件count非0,timed_out非0

if (count || timed_out)

break;

}

}

if (end_time

&& !to) {

expire

= timespec_to_ktime(*end_time);

to = &expire;

}

timed_out = 1;//表示休眠结束,就会在上面跳出这个死循环

}

大致流程就是这样,不同内核版本所用的处理函数不一样,下面来总结一下大体流程

(1)应用程序poll时会调用内核syy_poll,sys_poll调用do_sys_poll;

(2)do_sys_poll再调用 poll_initwait(&table);来进行一些初始化,初始化结果是pt->qproc

= qproc; =table->qproc =

__pollwait ,这在后面调用驱动力poll时用到;

(3)然后调用 do_poll(nfds, head, &table,

end_time),进入一个死循环,在里面调用do_pollfd(pfd,

pt),这个函数其实就是调用 mask

= file->f_op->poll(file,

pwait),也就是调用我们驱动程序的poll,驱程序会调用poll_wait(file,

&button_waitq,

wait),跟踪下去就知道这个函数最后会调用p->qproc(filp, wait_address,

p),也就是我们第二部初始化了p->qproc(filp, wait_address,

p),所以这里是调用 __pollwait (filp,&button_waitq,

p),它实现功能是把当前进程挂到button_waitq队列中 还没有休眠;

(4)如果驱动poll返回一个非0的值,上面count++,这也就说明了有按键按下了,上面就会break跳出循环,返回一个非0值;

(5)如果驱动poll返回一个0,说明我们没按下按键,这是就会往下执行 if

(end_time &&

!to),to初始化时0,我们在应用程序时回传进一个 end_time ,end_time不是0时if (end_time

&& !to) {

expire = timespec_to_ktime(*end_time);

to = &expire;

}

会一直在这里循环,当她数到0时跳出;

(6)然后就是 timed_out = 1,由上面if (count ||

timed_out)可知,这时也会跳出这个死循环,这时会返回0;

下面我们先看我们应用程序:

#include

#include

#include

#include

#include  //要把这个头文件加进来

int main()

{

int fd=-1;

unsigned char key;

int ret;//用来接收返回值

struct pollfd fds[1]; //定义一个struct

pollfd 结构体 //struct pollfd

{

// int fd; //short events;

//short revents;

};

fd = open("/dev/ccc",O_RDWR);

if(fd<0)

{

printf("can't open /dev/ccc\n");

return -1;

}

fds[0].fd = fd;//用来指定查询的驱动程序

fds[0].events =

POLLIN;//期待返回值,表示有数据等待读取,也就是说按键按下了

while(1)

{

ret =

poll(fds,1,5000);//查询一个文件,超时时间为5S

if(ret == 0)

{

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值