NAME
select
, pselect
— synchronous I/O
multiplexing
SYNOPSIS
#include
<sys/types.h>
#include <sys/time.h>
#include <string.h>
#include <unistd.h>
int
select
(int
nfds, fd_set
*readfds, fd_set
*writefds, fd_set
*exceptfds, struct
timeval *timeout);
int
pselect
(int
nfds, fd_set
*readfds, fd_set
*writefds, fd_set
*exceptfds, const struct
timespec *timeout, const
sigset_t *mask);
FD_SET
(fd,
&fdset);
FD_CLR
(fd,
&fdset);
FD_ISSET
(fd,
&fdset);
FD_ZERO
(&fdset);
DESCRIPTION
select
()
examines the I/O descriptor sets whose addresses are passed in
readfds, writefds, and
exceptfds to see if some of their descriptors are
ready for reading, are ready for writing, or have an exceptional condition
pending, respectively. The first nfds descriptors are
checked in each set; i.e., the descriptors from 0 through
nfds-1 in the descriptor sets are examined. On return,
select
() replaces the given descriptor sets with
subsets consisting of those descriptors that are ready for the requested
operation. select
() returns the total number of
ready descriptors in all the sets.
The descriptor sets are stored as bit fields in
arrays of integers. The following macros are provided for manipulating such
descriptor sets:
FD_ZERO
(&fdset)
initializes a descriptor set fdset to the null set.
FD_SET
(fd,
&fdset) includes a particular descriptor
fd in fdset.
FD_CLR
(fd,
&fdset) removes fd from
fdset.
FD_ISSET
(fd,
&fdset) is non-zero 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
, which is normally at
least equal to the maximum number of descriptors supported by the
system.
If timeout is a non-null
pointer, it specifies a maximum interval to wait for the selection to
complete. If timeout is a null pointer, the select
blocks indefinitely. To effect a poll, the timeout
argument should be non-null, pointing to a zero-valued timeval structure.
timeout is not changed by
select
(),
and may be reused on subsequent calls; however, it is good style to
re-initialize it before each invocation of
select
().
Any of readfds, writefds, and exceptfds may be given as null pointers if no descriptors are of interest.
The
pselect
()
function is similar to select
() except that it
specifies the timeout using a timespec structure. Also, if
mask is a non-null pointer,
pselect
() atomically sets the calling thread's
signal mask to the signal set pointed to by mask for
the duration of the function call. In this case, the original signal mask
will be restored before pselect
() returns.
RETURN VALUES
If successful, select
() and
pselect
() return the number of ready descriptors
that are contained in the descriptor sets. If a descriptor is included in
multiple descriptor sets, each inclusion is counted separately. If the time
limit expires before any descriptors become ready, they return 0.
Otherwise, if select
() or
pselect
() return with an error, including one due to
an interrupted call, they return -1, and the descriptor sets will be
unmodified.
ERRORS
An error return from select
() or
pselect
() indicates:
- [
EFAULT
] - One or more of readfds, writefds, or exceptfds points outside the process's allocated address space.
- [
EBADF
] - One of the descriptor sets specified an invalid descriptor.
- [
EINTR
] - A signal was delivered before the time limit expired and before any of the selected descriptors became ready.
- [
EINVAL
] - The specified time limit is invalid. One of its components is negative or too large.
SEE ALSO
accept(2), connect(2), gettimeofday(2), poll(2), read(2), recv(2), send(2), write(2), getdtablesize(3)
HISTORY
The select
() system call first appeared in
4.1cBSD. The pselect
()
system call has been available since OpenBSD
5.4.
BUGS
Although the provision of
getdtablesize(3) was intended to allow user programs to be
written independent of the kernel limit on the number of open files, the
dimension of a sufficiently large bit field for select remains a problem.
The default bit size of fd_set is based on the symbol
FD_SETSIZE
(currently 1024), but that is somewhat
smaller than the current kernel limit to the number of open files. However,
in order to accommodate programs which might potentially use a larger number
of open files with select, it is possible to increase this size within a
program by providing a larger definition of
FD_SETSIZE
before the inclusion of
⟨sys/types.h⟩. The kernel will cope,
and the userland libraries provided with the system are also ready for large
numbers of file descriptors.
Alternatively, to be really safe, it is possible to allocate fd_set bit-arrays dynamically. The idea is to permit a program to work properly even if it is execve(2)'d with 4000 file descriptors pre-allocated. The following illustrates the technique which is used by userland libraries:
fd_set *fdsr; int max = fd; fdsr = calloc(howmany(max+1, NFDBITS), sizeof(fd_mask)); if (fdsr == NULL) { ... return (-1); } FD_SET(fd, fdsr); n = select(max+1, fdsr, NULL, NULL, &tv); ... free(fdsr);
Alternatively, it is possible to use the
poll(2) interface.
poll(2) is more efficient when the size of
select
()'s fd_set bit-arrays
are very large, and for fixed numbers of file descriptors one need not size
and dynamically allocate a memory object.
select
() should probably have been
designed to return the time remaining from the original timeout, if any, by
modifying the time value in place. Even though some systems stupidly act in
this different way, it is unlikely this semantic will ever be commonly
implemented, as the change causes massive source code compatibility
problems. Furthermore, recent new standards have dictated the current
behaviour. In general, due to the existence of those brain-damaged
non-conforming systems, it is unwise to assume that the timeout value will
be unmodified by the select
() call, and the caller
should reinitialize it on each invocation. Calculating the delta is easily
done by calling
gettimeofday(2) before and after the call to
select
(), and using
timersub
() (as described in
getitimer(2)).
Internally to the kernel, select
() and
pselect
() work poorly if multiple processes wait on
the same file descriptor. Given that, it is rather surprising to see that
many daemons are written that way (i.e.,
httpd(8)).