ptg10805159
504 Advanced I/O Chapter 14
These interfaces can be implemented as either macros or functions. Anfd_setis
set to all zerobits by callingFD_ZERO.Toturn on a single bit in a set, we useFD_SET.
We can clear a single bit by callingFD_CLR.Finally, we can test whether a given bit is
turned on in the set withFD_ISSET.
After declaring a descriptor set, we must zerothe set usingFD_ZERO.Wethen set
bits in the set for each descriptor that we’reinterested in, as in
fd_set rset;
int fd;
FD_ZERO(&rset);
FD_SET(fd, &rset);
FD_SET(STDIN_FILENO, &rset);
On return fromselect, we can test whether a given bit in the set is still on using
FD_ISSET:
if (FD_ISSET(fd, &rset)) {
..
.
}
Any (or all) of the middle three arguments toselect(the pointers to the descriptor
sets) can be null pointers if we’renot interested in that condition. If all three pointers
areNULL,then we have a higher-precision timer than is provided bysleep.(Recall
from Section 10.19 thatsleepwaits for an integral number of seconds.Withselect,
we can wait for intervals less than one second; the actual resolution depends on the
system’s clock.) Exercise 14.5 shows such a function.
The first argument toselect,maxfdp1,stands for ‘‘maximum file descriptor plus
1.’’Wecalculate the highest descriptor that we’reinterested in, considering all three of
the descriptor sets, add 1, and that’s the first argument. Wecould just set the first
argument toFD_SETSIZE,aconstant in<sys/select.h>that specifies the maximum
number of descriptors (often 1,024), but this value is too large for most applications.
Indeed, most applications probably use between 3 and 10 descriptors. (Some
applications need many moredescriptors, but these UNIX programs areatypical.) By
specifying the highest descriptor that we’reinterested in, we can prevent the kernel
from going through hundreds of unused bits in the three descriptor sets, looking for bits
that areturned on.
As an example, Figure14.16 shows what two descriptor sets look like if we write
fd_set readset, writeset;
FD_ZERO(&readset);
FD_ZERO(&writeset);
FD_SET(0, &readset);
FD_SET(3, &readset);
FD_SET(1, &writeset);
FD_SET(2, &writeset);
select(4, &readset, &writeset, NULL, NULL);