select(), pselect()

QNX SDP8.0C Library ReferenceAPIDeveloper

Check for files that are ready for reading or writing or have an exceptional condition pending

Synopsis:

#include <sys/select.h>

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

int pselect( int width,
             fd_set * readfds,
             fd_set * writefds,
             fd_set * exceptfds,
             const struct timespec * restrict timeout,
             const sigset_t * restrict sigmask );

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 );

Arguments:

width
The number of descriptors to check in the given 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
readfds
NULL, or a pointer to an fd_set object that specifies the file descriptors to watch and see whether they are ready for reading. A file descriptor is ready for reading if a read operation will not block (this may include error returns or a file descriptor that is at end-of-file). The function replaces the set with the file descriptors that are actually ready for reading.
writefds
NULL, or a pointer to an fd_set object that specifies the file descriptors to watch and see whether they are ready for writing. A file descriptor is ready for writing if a write operation will not block (this includes error returns). The function replaces the set with the file descriptors that are actually ready for writing.
exceptfds
NULL, or a pointer to an fd_set object that specifies the file descriptors to watch and see whether they have an exceptional condition pending. The function replaces the set with the file descriptors that actually have an exceptional condition pending (if the driver/device define or support any such conditions).
timeout
NULL, or a pointer to a structure that specifies how long to wait for the selection to complete:
  • For select(), it's a struct timeval that specifies the timeout in seconds and microseconds.
  • For pselect(), it's a struct timespec that specifies the timeout in seconds and nanoseconds.
sigmask
(pselect() only) NULL, or a pointer to a sigset_t that specifies a signal mask to apply temporarily to the caller.

Library:

libc

Use the -l c option to qcc to link against this library. This library is usually included automatically.

Description:

Warning:

QNX recommends that you use poll() instead of select() to examine file descriptor sets.

The FD_SETSIZE setting determines the highest file descriptor number that the fd_set structure supports and must be set to one more than the highest file descriptor number that the fd_set objects use. The default FD_SETSIZE value of 256 is defined in <sys/select.h>. However, by default, QNX OS allows a maximum of 1000 file descriptors per process, which well exceeds this value. Using poll() instead of select() avoids errors caused by using the default value, and also is more efficient at handling a sparse list of file descriptors.

If you have to use select(), set FD_SETSIZE to the appropriate value in your code (e.g., 1001) before you include <sys/select.h> or <sys/time.h>. Your custom value will then be used in the typedef struct fd_set definition.

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, ready for writing, or have an exceptional condition pending. Any of these arguments may be NULL pointers if no descriptors are of interest.

The function replaces the given descriptor sets with subsets consisting of those descriptors that are ready for the requested operation, and returns the total number of ready descriptors in all the sets.

If timeout isn't NULL, it specifies a maximum interval to wait for the selection to complete. If timeout is NULL, 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 or timespec structure.

Note:
Because of the nature of time measurement, the function might actually wait longer than the specified time. Polling can also interfere with the kernel's efforts to manage power usage. For more information, see the Understanding the Microkernel's Concept of Time chapter of the QNX OS Programmer's Guide.

The pselect() function is similar to select(); if sigmask isn't NULL, pselect() replaces the caller's signal mask with the set of signals pointed to by sigmask before examining the descriptors, and restores the caller's signal mask before returning. Calling pselect() with a sigmask of NULL is the same as calling select(). Both select() and pselect() are implemented using poll().

The QNX OS implementation of select() is built on sending and handling an IO_NOTIFY message. You can use ionotify() if you want to combine input from file descriptors with QNX OS messaging in the same process. You can use select() when you're handling multiple file descriptors from sockets, pipes, serial ports, and so on.

If you use select() with a timeout, you should reset the timeout value after calling select().

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

Manipulating file-descriptor sets

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

FD_ZERO( &fdset )
Initialize 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 )
Remove fd from fdset.
FD_ISSET( fd, &fdset )
Is nonzero if fd is a member of fdset; otherwise, zero.

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

Returns:

The number of ready descriptors in the descriptor sets, 0 if the timeout expired, or -1 if an error occurs (errno is set).

Errors:

EBADF
One of the descriptor sets specified an invalid descriptor.
EFAULT
One of the pointer arguments referred to a nonexistent portion of the calling process's address space.
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.
ENOMEM
There was not enough memory.

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/select.h>

int 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" );
      return 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" );
        return 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" );
    }
    return EXIT_SUCCESS;
}

Classification:

POSIX 1003.1

Safety:
Cancellation pointYes
Signal handlerNo
ThreadRead the Caveats

Caveats:

The select() function works only 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.

The select() function is thread safe as long as the fd sets used by each thread point to memory that is specific to that thread.

In QNX OS, if multiple threads block in select() on the same fd for the same condition, all threads may unblock when the condition is satisfied. This may differ from other implementations where only one thread may unblock.

Page updated: