NAME
select,
pselect —
synchronous I/O multiplexing
LIBRARY
Standard C Library (libc, -lc)
SYNOPSIS
#include <sys/select.h>
int
select(
int
nfds,
fd_set * restrict
readfds,
fd_set * restrict
writefds,
fd_set * restrict
exceptfds,
struct timeval *
restrict timeout);
int
pselect(
int
nfds,
fd_set * restrict
readfds,
fd_set * restrict
writefds,
fd_set * restrict
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);
DESCRIPTION
select() and
pselect() examine 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. This means that
nfds must be set to the
highest file descriptor of the three sets, plus one. On return,
select() and
pselect() replace the given
descriptor sets with subsets consisting of those descriptors that are ready
for the requested operation.
select() and
pselect() return 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 pointed to by
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 poll without blocking, the
timeout
argument should be non-null, pointing to a zero-valued timeval or timespec
structure, as appropriate.
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().
If
sigmask is a non-null pointer, then the
pselect() function shall replace the signal mask of the
caller by the set of signals pointed to by
sigmask
before examining the descriptors, and shall restore the signal mask of the
calling thread before returning.
Any of
readfds,
writefds, and
exceptfds may be given as null pointers if no
descriptors are of interest.
NOTES
It is recommended to use the
poll(2)
interface instead, which tends to be more portable and efficient.
RETURN VALUES
select() returns the number of ready descriptors that are
contained in the descriptor sets, or -1 if an error occurred. If the time
limit expires,
select() returns 0. If
select() returns with an error, including one due to an
interrupted call, the descriptor sets will be unmodified.
EXAMPLES
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <err.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/time.h>
int
main(int argc, char **argv)
{
fd_set read_set;
struct timeval timeout;
int ret, fd, i;
/* file descriptor 1 is stdout */
fd = 1;
/* Wait for ten seconds. */
timeout.tv_sec = 10;
timeout.tv_usec = 0;
/* Initialize the read set to null */
FD_ZERO(&read_set);
/* Add file descriptor 1 to read_set */
FD_SET(fd, &read_set);
/*
* Check if data is ready to be read on
* file descriptor 1, give up after 10 seconds.
*/
ret = select(fd + 1, &read_set, NULL, NULL, &timeout);
/*
* Returned value is the number of file
* descriptors ready for I/O, or -1 on error.
*/
switch (ret) {
case -1:
err(EXIT_FAILURE, "select() failed");
break;
case 0:
printf("Timeout, no data received.\n");
break;
default:
printf("Data received on %d file descriptor(s)\n", ret);
/*
* select(2) hands back a file descriptor set where
* only descriptors ready for I/O are set. These can
* be tested using FD_ISSET
*/
for (i = 0; i <= fd; i++) {
if (FD_ISSET(i, &read_set)) {
printf("Data on file descriptor %d\n", i);
/* Remove the file descriptor from the set */
FD_CLR(fd, &read_set);
}
}
break;
}
return 0;
}
ERRORS
An error return from
select() indicates:
-
-
- [
EBADF
]
- One of the descriptor sets specified an invalid
descriptor.
-
-
- [
EFAULT
]
- One or more of readfds,
writefds, or exceptfds points
outside the process's allocated address space.
-
-
- [
EINTR
]
- A signal was delivered before the time limit expired and
before any of the selected events occurred.
-
-
- [
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() function call appeared in
4.2BSD.
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 256), 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.
Note:
rpc(3) library uses
fd_set with the default
FD_SETSIZE
as part of its ABI. Therefore, programs
that use
rpc(3) routines cannot
change
FD_SETSIZE
.
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 = (fd_set *)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);
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
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() works poorly if multiple
processes wait on the same file descriptor.