驱动支持select函数

I/O多路转接至今还不是 POSIX的组成部分。SVR4和 4.3 + BSD都提供select函数以执行I/O多路转接。poll函数只由SVR4 提供。SVR4 实际上用poll实现select。I/O多路转接的基本思想是:先构造一张有关描述符的表,然后调用一个函数,它要到这些描述符中的一个已准备好进行 I/O时才返回。在返回时,它告诉进程哪一个描述符已准备好可以进行 I/O。
 
I/O多路转接在服务器端用的比较多,可以同时处理多个连接的接入,但是也有缺陷,貌似只能接受1024个接入,因此现在又了epoll,当然这不是讨论的重点了。
 
select的函数原型为:
 
int select(int  numfds,  fd_set  *readfds,  fd_set  *writefds,  fd_set  *exceptfds,  struct  timeval  *timeout);
 
 
 
其中 readfds、writefds、exceptfds 分别是被 select()监视的读、写和异常处理的文件描述符集合,numfds 的值是需要检查的号码最高的文件描述符加 1。timeout 参数是一个指向 struct timeval类型的指针,它可以使select()在等待timeout时间后若没有文件描述符准备好则返回。
 
struct timeval 数据结构为: 
 
struct timeval 
 

 
    int tv_sec; /* seconds */ 
 
    int tv_usec; /* microseconds */ 
 
};
 
除此之外,我们还将使用下列 API:
 
FD_ZERO(fd_set *set)――清除一个文件描述符集; 
 
FD_SET(int fd,fd_set *set)――将一个文件描述符加入文件描述符集中; 
 
FD_CLR(int fd,fd_set *set)――将一个文件描述符从文件描述符集中清除; 
 
FD_ISSET(int fd,fd_set *set)――判断文件描述符是否被置位。
 
 
 
select 用于查询设备的状态,以便用户程序获知是否能对设备进行非阻塞的访问,需要设备驱动程序中的poll 函数支持。 驱动程序中 poll 函数中最主要用到的一个 API 是 poll_wait,其原型如下:
 
void poll_wait(struct file *filp, wait_queue_heat_t *queue, poll_table * wait);
 
poll_wait 函数所做的工作是把当前进程添加到 wait 参数指定的等待列表(poll_table)中。
 
需要说明的是,poll_wait 函数并不阻塞,程序中 poll_wait(filp, &outq, wait)这句话的意思并不是说一直等待 outq 信号量可获得,真正的阻塞动作是上层的 select/poll 函数中完成的。select/poll 会在一个循环中对每个需要监听的设备调用它们自己的 poll 支持函数以使得当前进程被加入各个设备的等待列表。若当前没有任何被监听的设备就绪,则内核进行调度(调用 schedule)让出 cpu 进入阻塞状态,schedule 返回时将再次循环检测是否有操作可以进行,如此反复;否则,若有任意一个设备就绪,select/poll 都立即返回。
 
针对前面的文章的程序,我们在驱动中加入对poll的支持,程序改进为:
 
/*  global_poll.c */
 
#include <linux/module.h>
 
#include <linux/init.h>
 
#include <linux/fs.h>
 
#include <asm/uaccess.h>
 
#include <linux/wait.h>
 
#include <linux/semaphore.h>
 
#include <linux/device.h>
 
#include <linux/cdev.h>
 
#include <linux/sched.h>
 
#include <linux/poll.h>
 
 
 
MODULE_LICENSE("GPL");
 
 
 
#define init_MUTEX(LOCKNAME) sema_init(LOCKNAME,1)
 
 
 
 
 
#define DEVICE_NAME "CDEV_ZHU"
 
static struct class *cdev_class;
 
 
 
struct cdev dev_c;
 
dev_t dev;
 
 
 
static ssize_t globalvar_read(struct file *, char *, size_t, loff_t*);
 
static ssize_t globalvar_write(struct file *, const char *, size_t, loff_t*);
 
static unsigned int globalvar_poll(struct file *filp, poll_table *wait);
 
 
 
struct file_operations globalvar_fops =
 
{
 
read: globalvar_read,
 
write: globalvar_write,
 
poll: globalvar_poll,
 
};
 
 
 
static int global_var = 0;
 
static struct semaphore sem;
 
static wait_queue_head_t outq;
 
static int flag = 0;
 
 
 
static int __init globalvar_init(void)
 
{
 
int ret,err;
 
ret = alloc_chrdev_region(&dev,0,1,DEVICE_NAME) ;
 
if (ret)
 
{
 
printk("globalvar register failure");
 
}
 
else
 
{
 
 

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:http://www.heiqu.com/8b967cff3231c4939ad5eda8dcfe18b4.html