poll机制总结

总结:

1. poll > sys_poll > do_sys_poll >poll_initwait,poll_initwait函数注册一下回调函数__pollwait,它就是我们的驱动程序执行poll_wait时,真正被调用的函数。 

2. 接下来执行file->f_op->poll,即我们驱动程序里自己实现的poll函数

   它会调用poll_wait把自己挂入某个队列,这个队列也是我们的驱动自己定义的;

   它还判断一下设备是否就绪。 

3. 如果设备未就绪,do_sys_poll里会让进程休眠一定时间,这个时间是应用提供的“超时时间” 

4. 进程被唤醒的条件有2:一是上面说的“一定时间”到了,二是被驱动程序唤醒。驱动程序发现条件就绪时,就把“某个队列”上挂着的进程唤醒,这个队列,就是前面通过poll_wait把本进程挂过去的队列。 

5. 如果驱动程序没有去唤醒进程,那么chedule_timeout(__timeou)超时后,会重复2、3动作1次,直到应用程序给定的时间, 然后返回。

 

驱动的poll函数编写模板如下:

static DECLARE_WAIT_QUEUE_HEAD(my_waitq);  //休眠要挂的等待队列

static unsigned drv_poll(struct file *file, poll_table *wait)
{
unsigned int mask = 0;
poll_wait(file, &my_waitq, wait); // 不会立即休眠
if (有数据)
mask |= POLLIN | POLLRDNORM;
return mask;
}

 

 

 

实例:

 

 

在驱动函数中

前面要加一个等待队列,

static unsigned forth_drv_poll(struct file *file, poll_table *wait)
{
    unsigned int mask = 0;
    poll_wait(file, &button_waitq, wait); // 不会立即休眠

    if (a)                  //这个是自己定的有数据的标志,在中断函数中定义了一个标志位,如果这个标志位为1的时候,表示已经收到数据了
        mask |= 1 ;//这个mask的值可以随便定,但是要和应用程序中 fds[0].events的值一样,这样才会符合

    return mask;
}

 


在应用程序中

    fds[0].fd     = fd;

    fds[0].events = 1

    ret = poll(fds, 1, 1000);//ret = 1 ;

if(ret == 0)

{

三个条件都没有满足
}

else{

有数据时做什么

}

 

 

 

总的来说就是,先加入到等待队列,然后利用mask唤醒

你可能感兴趣的:(JZ2440)