world leader in high performance signal processing
Trace: » polling

Device Driver POLL interface

Sometimes a program wants to wait on events from several devices. A time out can also be used so that the system can perform housekeeping or diagnostic tasks while waiting.

In BSD Unix systems this was done using the old select system call. More detailed control options are provided by the System V poll interface.

The device driver code is always provided by the poll interface. This interface is quite simple with the underlying kernel systems providing much of the required infrastructure.

The system uses a poll_wait call to indicate that the poll system is interested in events. The poll_wait call includes a reference to a wait queue that must be triggered by a driver event. Another argument to poll_wait function is a poll_table structure. This is used as an opaque object only.

The driver poll function has two main duties to perform.

  • Register any wait queues used by the driver with the poll system.
  • Check for any pending events and return a mask with appropriate bits set.

The mask is returned in the events member of the pollfd structure. The include file sys/poll.h defines the bit masks.

The following table describes the most significant bit meanings:

Name Description
POLLIN Set when normal data can be read without blocking
POLLPRISet when High Priority data (out-of-band) can be read without blocking
POLLHUPSet when the device sees “end-of-file”
POLLERRSet when an error condition has occurred on the device
POLLOUTSet when normal data can be WRITTEN without blocking

POLL in User Space

The user space interface is: int POLL(pollfd_structure , int count , int timeout ) An example:

  /* pollfds structure , number of files of interest , timeout in mS */
  result = poll(pfds, 1, 1000);                                        

The pollfd structure needs to be set up with the file descriptor and events of interest as follows;

  struct pollfd pfds[NUM_POLLFDS];                            
  /* get the fd for the device using an open call */          
  /* select events of interest  in this case read and write */

SELECT in User Space

The select call in user space is more complex. It will only work where the io device has been set up as NON BLOCKING. The following is an example of setting up a socket as NON BLOCKING.

  #include <ctype.h>                   
  #include <sys/time.h>                
  #include <fcntl.h>                   
  ...(stuff missing)                                  
   int ret;                            
   ret  = fcntl(socket,F_GETFL);       
   if (ret < 0) {                      
   ret = (ret | O_NONBLOCK);           
   if (fcntl(socket,F_SETFL,ret) < 0) {

The select man page gives a good example on how to use the select function in user space.

  #include <stdio.h>                                   
  #include <sys/time.h>                                
  #include <sys/types.h>                               
  #include <unistd.h>                                  
  int main(void) {                                     
     fd_set rfds;                                      
     struct timeval tv;                                
     int retval;                                       
     /* Watch stdin (fd 0) to see when it has input. */
     /* Wait up to five seconds. */                    
     tv.tv_sec = 5;                                    
     tv.tv_usec = 0;                                   
     retval = select(1, &rfds, NULL, NULL, &tv);       
     /* Don't rely on the value of tv now! */          
     if (retval) {                                     
        printf("Data is available now.\n");            
        /* FD_ISSET(0, &rfds) will be true. */         
     } else  {                                         
        printf("No data within five seconds.\n");      

Poll Example code

The select feature is provided in linux by using the basic poll system.

This is the driver poll code The poll call must return a mask of events set whenever it it called. When the user code issues a poll system call this code is used in the driver to register interest in all the possible events that could change the state of the device. When one or more of those events occur the poll function will be called again automatically by the kernel to allow the state of the driver to be re-evaluated.

  #include <linux/poll.h>                                           
  int scmd_poll(struct file* filp , poll_table * pwait)             
     int canwrite, canread;                                         
     unsigned int mask=0;                                           
     scmd_dev_t * dev;                                              
     dev = (scmd_dev_t *) filp->private_data;                       
     poll_wait(filp,&dev->inq, pwait);                              
     poll_wait(filp,&dev->outq, pwait);                             
     canwrite = ((dev->rp + SCMD_SIZE - dev->wp ) % SCMD_SIZE) != 1;
     canread = (dev->rp != dev->wp);                                
     if (canread) mask |= POLLIN | POLLRDNORM;                      
     if (canwrite) mask |= POLLOUT | POLLWRNORM;                    
     return mask;                                                   

Poll Fops Table

The fops table needs to be set up in the driver init function

    scmd_driver_fops.write = scmd_write;              
    // set up the poll function                       
    scmd_driver_fops.poll = scmd_poll;                

Poll User code

A typical poll user code example

  // test_poll.c simple test for poll
  // cc -O2 -o test_poll test_poll.c 
  #include <fcntl.h>                 
  #include <unistd.h>                
  #include <sys/types.h>             
  #include <sys/poll.h>              
  #include "scmd_poll.h"             
  int main () {                                                          
    char buffer[128];                                                    
    int i = 0, result, nread;                                            
    struct pollfd pollfds[2];                                            
    int timeout = 2000;           /* Timeout in msec. */                 
    /* Initialize pollfds; we're looking at input from /dev/scmd*/       
    pollfds[0].fd = open("/dev/scmd",O_RDWR);                            
    if ( pollfds[0].fd  < 0 ) {                                          
      printf(" failed to open /dev/scmd \n");                            
      exit (1);                                                          
    pollfds[0].events = POLLIN;      /* Wait for input */                
    while (1) {                                                          
        result = poll (&pollfds, 1, timeout);                            
        switch (result) {                                                
          case 0:                                                        
            printf ("timeout\n");                                        
          case -1:                                                       
            printf ("poll error \n");                                    
            exit (1);                                                    
            if (pollfds[0].revents & POLLIN) {                           
                nread = read (pollfds[0].fd, buffer, SCMD_SIZE);         
                if (nread == 0) {                                        
                    printf ("/dev/scmd done\n");                         
                    exit (0);                                            
                } else {                                                 
                    buffer[nread] = 0;                                   
                    printf ("read %d from /dev/scmd: %s", nread, buffer);
    return 0;