| 
		    
                    
   驱动程序中poll函数中最主要用到的一个API是poll_wait,其原型如下: 
 
    
        
            | void poll_wait(struct file *filp, wait_queue_heat_t *queue, poll_table * wait); | 
         
    
 
  poll_wait函数所做的工作是把当前进程添加到wait参数指定的等待列表(poll_table)中。下面我们给globalvar的驱动添加一个poll函数:
  
 
    
        
            static unsigned int globalvar_poll(struct file *filp, poll_table *wait) {  unsigned int mask = 0;
   poll_wait(filp, &outq, wait);
   //数据是否可获得?   if (flag != 0)  {   mask |= POLLIN | POLLRDNORM; //标示数据可获得  }  return mask; } | 
         
    
 
  需要说明的是,poll_wait函数并不阻塞,程序中poll_wait(filp, &outq, wait)这句话的意思并不是说一直等待outq信号量可获得,真正的阻塞动作是上层的select/poll函数中完成的。select/poll会在一个循环中对每个需要监听的设备调用它们自己的poll支持函数以使得当前进程被加入各个设备的等待列表。若当前没有任何被监听的设备就绪,则内核进行调度(调用schedule)让出cpu进入阻塞状态,schedule返回时将再次循环检测是否有操作可以进行,如此反复;否则,若有任意一个设备就绪, select/poll都立即返回。 
   我们编写一个用户态应用程序来测试改写后的驱动。程序中要用到BSD Unix中引入的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)――判断文件描述符是否被置位。 
  下面的用户态测试程序等待/dev/globalvar可读,但是设置了5秒的等待超时,若超过5秒仍然没有数据可读,则输出"No data within 5 seconds": 
 
    
        
            | 
             #include <sys/types.h> #include <sys/stat.h> #include <stdio.h> #include <fcntl.h> #include <sys/time.h> #include <sys/types.h> #include <unistd.h> 
             | 
         
    
 
		    
                      
		      
		      
		   |