Using the select System Call


The select system call is a general-purpose tool that allows UNIX processes to wait for a device to become available. select covers much more than just serial ports; it can handle message queues and network streams. See your UNIX documentation for the full details: The following is a simplified description for our purposes. The call has the following syntax:

#include <sys/select.h>
long select(Nfdsmsgs, ReadList, WriteList, ExceptList, TimeOut)
int nfd;
fd_set *ReadList, *WriteList, *ExceptList;
struct timeval *TimeOut;

Nfdsmsgs is the number of file descriptors to check (or the highest to check, plus one). ReadList is a structure containing a bitmap of the file descriptors to check for read availability. WriteList is a bitmap for write availability, and ExceptList is a bitmap for an exception waiting on a port.

TimeOut specifies how long to wait for one of the requirements to be met before returning with no action. If TimeOut is NULL, the call will wait indefinitely. If all the fields of TimeOut contain zero, select will return immediately with the state of all requested file descriptors.

select returns two values packed into a long. The high 16 bits contain the number of network streams that were satisfied; the low 16 bits contain the number of normal devices that were satisfied. select returns zero if a timeout condition occurred, -1 upon failure.

File Descriptors

select accepts a bitmap which specifies the file descriptors you want to "check in" (wait on). The typedef fd_set describes this bitmap:

typedef struct fd_set {
    fd_mask fds_bits[N];
}

The type of fd_mask, and the value of N, is system dependent. Under AIX, fd_mask is a 32-bit int, and N is 64, giving a range of 2,048 file possible descriptors. An expanded structure exists for using select in more sophisticated ways; see your UNIX documentation for details.

There are several convenience macros for setting and testing the bits:

A word of caution about the select call's portability: on many UNIX systems it is up to the character device driver to implement select support, and some older device drivers may not include support. These may quietly fail without giving an error code. Most modern serial devices include support, however, so this should rarely be a problem.

Another call in the UNIX world, known as poll, performs a similar function. The poll subroutine does not need all the bit manipulation, and is much easier to use than select. If portability is an issue, however, select is the more portable of the two. o