用中断来实现按键驱动程序里面,如果我们一直没有按键按下触发中断应用程序会一直的在休眠,现在我们想让它隔一段时间就返回一个值要怎么做呢,这就是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)
{
printf("time out\n");
}
else{