poll设备方法

来源:互联网 发布:网站美工制作 编辑:程序博客网 时间:2024/06/02 04:36

当应用程序需要进行对多文件读写时,常用到 pollSystem V)、selectBSD Unix)、 epoll(linux2.5.45开始)(没验证)系统调用配合使用。poll函数返回时,会给出一个文件是否可读写的标志,应用程序根据不同的标志读写相应的文件,实现阻塞或非阻塞的读写。这些系统调用功能相同:允许进程来决定它是否可阻塞或非阻塞的读写一个或多个文件。这些调用都需要来自设备驱动中poll方法的支持,poll返回不同的标志,告诉主进程文件是否可以读写,其原型(定义在<linux/poll.h>:
实现这个设备方法分两步:
 
1.使用poll_wait将等待队列添加到poll_table中。
#include <linux/poll.h>
static inline void poll_wait (struct file *filp, wait_queue_head_t *wait_address, poll_table *P);
增加wait_queue_head_t等待队列到poll_tabl中。
 
2. 返回描述设备是否可读或可写的掩码。几个标志(通过 <linux/poll.h>定义)用来指示可能的操作:
 
 
标志
含义
POLLIN
 
如果设备无阻塞的读,就返回该值(设备可读)
 POLLRDNORM
 
 通常的数据已经准备好,可以读了,就返回该值。通常的做法是会返回(POLLLIN|POLLRDNORA
(数据可读)
 POLLRDBAND 如果可 以从设备读出带外数据,就返回该值,它只可在linux内 核的某些网络代码中使用,通常不用在设备驱动程序中 POLLPRI
 如果可 以无阻塞的读取高优先级(带外)数据,就返回该值,返回该值会导致select报告文件发生异常,以为select八带外数据当作异常处理
 
 POLLHUP
 当读设 备的进程到达文件尾时,驱动程序必须返回该值,依照select的功能描述,调用select的进程被告知进程时可读的。
 
 POLLERR
 如果设 备发生错误,就返回该值。
 
POLLOUT
 如果设备可以无阻塞地写,就返回该值(设备可写)
 
 POLLWRNORM
 设备已经准备好,可以写了,就返回该值。通常地做法是(POLLOUT|POLLNORM
(数据可写)
 POLLWRBAND
 POLLRDBAND类似
 

设备和数据在使用上实际上没有任何差别,通常可读返回:POLLIN|POLLRDNORM,可写返回:POLLOUT|POLLWRNORM
应当重复一下 POLLRDBAND POLLWRBAND 仅仅对关联到 socket的文件描述符有意义: 通常设备驱动不使用这些标志。
poll 的描述使用了大量在实际使用中相对简单的东西.考虑 poll 方法的 scullpipe实现:
static unsigned int scull_p_poll(struct file *filp, poll_table *wait)
{
struct scull_pipe *dev = filp->private_data;
        unsigned int mask = 0;
/*       * The buffer is circular; it is considered full
        * if "wp" is right behind "rp" and empty if the
        * two are equal. 
 */
down(&dev->sem);
        poll_wait(filp, &dev->inq,  wait);
        poll_wait(filp, &dev->outq, wait);
        if (dev->rp != dev->wp)
                mask |= POLLIN | POLLRDNORM;  /* readable */
up(&dev->sem);
        return mask;
}
这个代码简单地增加了 2 scullpipe 等待队列到 poll_table,接着设置正确的掩码位, 根据数据是否可以读或写.
所示的 poll代码缺乏文件尾支持, 因为 scullpipe不支持文件尾情况. 对大部分真实的设备, poll 方法应当返回 POLLHUP 如果没有更多数据(或者将)可用.如果调用者使用 select 系统调用,文件被报告为可读. 不管是使用 poll还是 select, 应用程序知道它能够调用 read 而不必永远等待,并且 read 方法返回 0来指示文件尾.
 
范例
static unsigned int mem_poll(struct file *filp,poll_table *wait)
{
struct scull_piple *dev =filp->private_data;
?//为什么要使用scull_piple, scull_piple是针对一片内存实现一个环形缓,用缓冲的目的是存储队列。
unsigned int mask =0;
 
/*把进程添加到等待队列*/
poll_wait(filp,&dev->inq,wait);
 
/*返回掩码*/
If(数据有效)
         mask=POLLIN|POLLRDNRM;/*设备可读*/
return mask;
}
Poll方法只是做一个登记,真正的阻塞发生在select.c中的do_select函数。

1 0
原创粉丝点击