The interface to select()
is primarily based on the concept of an
fd_set
, which is a set of FDs (usually implemented as a
bit-vector). In times past, it was common to assume that FDs were
smaller than 32, and just use an int to store the set, but these days,
one usually has more FDs available, so it is important to use the
standard macros for manipulating fd_sets:
fd_set set;
FD_ZERO(&set); /* empties the set */
FD_SET(fd,&set); /* adds FD to the set */
FD_CLR(fd,&set); /* removes FD from the set */
FD_ISSET(fd,&set) /* true if FD is in the set */
In most cases, it is the system's responsibility to ensure that fdsets
can handle the whole range of file descriptors, but in some cases you
may have to predefine the FD_SETSIZE
macro.
This is system-dependent;
check your select()
manpage. Also, some systems have problems
handling more than 1024 file descriptors in select()
.
The basic interface to select is simple:
int select(int nfds, fd_set *readset,
fd_set *writeset,
fd_set *exceptset, struct timeval *timeout);
where
nfds
readset
writeset
exceptfds
timeout
tv_sec
and tv_usec
both equal zero, then the
The call returns the number of `ready' FDs found, and the three fdsets
are modified in-place, with only the ready FDs left in the sets. Use the
FD_ISSET
macro to test the returned sets.
Here's a simple example of testing a single FD for readability:
int isready(int fd)
{
int rc;
fd_set fds;
struct timeval tv;
FD_ZERO(&fds);
FD_SET(fd,&fds);
tv.tv_sec = tv.tv_usec = 0;
rc = select(fd+1, &fds, NULL, NULL, &tv);
if (rc < 0)
return -1;
return FD_ISSET(fd,&fds) ? 1 : 0;
}
Note that we can pass NULL
for fdsets that we aren't interested
in testing.