设备驱动中的轮询编程
unsigned int(*poll)(struct file *filp, struct poll_table *wait);
第一个参数为文件指针,第二个参数为轮询表指针,原型定义如下:
poll()函数主要进行2项工作:
a. 对可能引起设备文件状态变化的等待队列, 调用poll_wait()函数,将对应的等待队列头添加到poll_table.
b.返回表示是否能对设备进行无阻塞读、写反问。poll()函数返回一个位掩码:
描述可能不必阻塞就立刻进行的操作,几个标志(通过 <linux/poll.h> 定义)用来指示可能的操作:
标志 | 含义 |
POLLIN | 如果设备无阻塞的读取,就返回该值 |
POLLRDNORM | 通常的数据已经准备好可以读了,就返回该值。一个可读设备返回(POLLLIN | POLLRDNORM) |
POLLRDBAND | 如果可以从设备读出带外数据,就返回该值,它只可在与套接字相关的的文件描述符中使用,通常不用在设备驱动程序中 |
POLLPRI | 如果可以无阻塞的读取高优先级(oob带外)数据,就返回该值,返回该值会导致select报告文件发生异常,以为select把带外数据当作异常处理 |
POLLHUP | 当读设备的进程到达文件尾时,驱动程序必须返回该值,依照select的功能描述,调用select的进程被告知进程时可读的。 |
POLLERR | 如果设备发生错误,就返回该值。 |
POLLOUT | 如果设备可以无阻塞地写入,就返回该值 |
POLLWRNORM | 设备已经准备好,可以写了,就返回该值。一个可写设备返回(POLLOUT | POLLNORM) |
POLLWRBAND | 于POLLRDBAND类似 |
poll 识别3类数据 普通,优先级带,和高优先级 ,一般TCP,UDP 属于普通数据。
poll_wait() 把当前文件描述符添加到 wait参数 指定的等待列表(poll_table)中。
poll_table在<linux/poll.h>中声明,
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);
}
示例:
用户空间的poll() 或select()函数,会系统调用到驱动中的 xxx_poll() 函数。
/*globalfifo poll函数*/
static unsigned int globalfifo_poll(struct file *filp, poll_table *wait)
{
unsigned int mask = 0;
struct globalfifo_dev *dev = filp->private_data; /*获得设备结构体指针*/
down(&dev->sem);
poll_wait(filp, &dev->r_wait, wait); /* poll_wait 将*/
poll_wait(filp, &dev->w_wait, wait);
/*只有fifo非空时, 才可读*/
if (dev->current_len != 0)
{
mask |= POLLIN | POLLRDNORM; /*标示数据可获得*/
}
/*只有fifo非满时,才可写*/
if (dev->current_len != GLOBALFIFO_SIZE)
{
mask |= POLLOUT | POLLWRNORM; /*标示数据可写入*/
}
up(&dev->sem);
return mask;
}