[Previous]
[Contents]
[Next]

select()

check for files that are ready for reading or writing

Synopsis:

#include <sys/select.h>

int select ( int width,
             fd_set *readfds,
             fd_set *writefds,
             fd_set *exceptfds,
             struct timeval *timeout );

FD_SET   ( int fd, fd_set *fdset );
FD_CLR   ( int fd, fd_set *fdset );
FD_ISSET ( int fd, fd_set *fdset );
FD_ZERO  ( fd_set *fdset );

Description:

The select() function examines the file descriptor sets whose addresses are passed in readfds, writefds, and exceptfds to see if some of their descriptors are ready for reading, writing, or have an exceptional condition pending.

The width argument controls the number of descriptors select() will examine within the descriptor sets. Only the descriptors from 0 through (width-1) in the descriptor sets are examined. Therefore, the value of width must be at least as large as:

(highest valued file descriptor in the sets) +1

On return, the select() function replaces the given descriptor sets with subsets consisting of those descriptors that are ready for the requested operation. The total number of ready descriptors in all the sets is returned.

At least the following macros are defined in <sys/select.h> for manipulating these descriptor sets:

FD_ZERO(&fdset)
Initializes a descriptor set fdset to the null set.
FD_SET(fd, &fdset)
Add the file descriptor fd to the set fdset.
FD_CLR(fd, &fdset)
Removes fd from fdset.
FD_ISSET(fd, &fdset)
Is nonzero if fd is a member of fdset, zero otherwise.

The behavior of these macros is undefined if a descriptor value is less than zero or greater than or equal to FD_SETSIZE.

If timeout isn't a NULL pointer, it specifies a maximum interval to wait for the selection to complete. If timeout is a NULL pointer, then select() blocks until one of the selected conditions occurs. To effect a poll, the timeout argument should be a non-NULL pointer, pointing to a zero-valued timeval structure.

Any of readfds, writefds, and exceptfds may be NULL pointers if no descriptors are of interest.

If the current operating system configuration supports a larger number of open files than is specified in FD_SETSIZE, it's possible for a program to increase the number of open file descriptors used with select() by increasing the definition of FD_SETSIZE before the inclusion of <sys/select.h>.

Programs using select() with a timeout should reset their timeout value after calling select(). (In QNX, on return from the select() call, timeout contains the amount of time remaining, and not the original timeout value. However, this may not be portable).


Note: If you're using select() in conjunction with the socket API package, it's important to note that selecting for reading on a socket descriptor on which a listen() has been performed indicates that a subsequent accept() on that descriptor will not block.

In the QNX implementation of select(), once the resource manager(s) have been armed to wait for the specified file descriptors (and possibly a timer has been set up), select() calls the internal function _select_receive() to wait for its proxy to be triggered. The prototype for this (otherwise undocumented) function is as follows:

pid_t _select_receive( pid_t proxy )

This function does a specific Receive() on its proxy argument. A trigger on this proxy indicates to select() that one of the descriptors has become ready, or the timer has expired.

You can provide an alternate version of this function if you wish to perform other actions as well as waiting for the specific proxy to be triggered. One example would be to do a Receive(0,...) if you wanted to receive other messages during a call to select().

Note that the select_receive() function shouldn't return until the proxy it was passed has been triggered. It must also return the proxy, or -1 to indicate an error occurred.

Returns:

A nonnegative value on success. A positive value indicates the number of ready descriptors in the descriptor sets. A return value of 0 indicates that the time limit referred to by timeout expired.

On failure, the select() function returns -1, sets errno to indicate the error, and the descriptor sets aren't changed.

Errors:

EBADF
One of the descriptor sets specified an invalid descriptor.
EFAULT
One of the pointers given in the call referred to a nonexistent portion of the address space for the process.
EINTR
A signal was delivered before any of the selected events occurred, or before the time limit expired.
EINVAL
A component of the pointed-to time limit is outside the acceptable range: t_sec must be between 0 and 10^8, inclusive. t_usec must be greater than or equal to 0, and less than 10^6. 10 to the power of 8, inclusive. t_usec must be greater than or equal to 0, and less than 10 to the power of 6.

Examples:

/*
 *  This example opens a console and a serial port for
 *  read mode, and calls select() with a 5 second timeout.
 *  It waits for data to be available on either descriptor.
 */

#include <unistd.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/time.h>
#include <sys/select.h>

void main( void )
  {
    int console, serial;
    struct timeval tv;
    fd_set rfd;
    int n;

    if( ( console = open( "/dev/con1", O_RDONLY ) ) == -1
    ||    ( serial  = open( "/dev/ser1", O_RDONLY ) ) == -1 )
    {
      perror( "open" );
      exit( EXIT_FAILURE );
    }

    /*
     * Clear the set of read file descriptors, and
     * add the two we just got from the open calls.
     */
    FD_ZERO( &rfd );
    FD_SET( console, &rfd );
    FD_SET( serial,  &rfd );

    /*
     *    Set a 5 second timeout.
     */
    tv.tv_sec = 5;
    tv.tv_usec = 0;

    switch ( n = select( 1 + max( console, serial ),
           &rfd, 0, 0, &tv ) ) {
      case -1:
        perror( "select" );
        exit( EXIT_FAILURE );
      case  0:
        puts( "select timed out" );
        break;
      default:
        printf( "%d descriptors ready ...\n", n );
        if( FD_ISSET( console, &rfd ) )
          puts( " -- console descriptor has data pending" );
        if( FD_ISSET( serial, &rfd ) )
          puts( " -- serial descriptor has data pending" );
    }
    exit( EXIT_SUCCESS );
  }

Classification:

UNIX

Safety:
Interrupt handler No
Signal handler No
Thread No

Caveats:

The select() function only works with raw file descriptors; it doesn't work with file descriptors in edited mode. See the ICANON flag in the description of the tcgetattr() function.

See also:

dev_arm(), dev_readex(), errno, fcntl(), read(), sysconf(), tcsetattr(), write()


[Previous]
[Contents]
[Next]