Advanced I/O, Part 2

select() is declared in

as follows: #include #include int select(int highestfd, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout); The first parameter is the highest file descriptor listed in all three sets + 1. Thus, if our process watches 2 file descriptors numbered 0 and 1, highestfd should be 2. The second, third, and forth parameters are pointers to fd_set -- a data structure containing a set of file descriptors to watch. Any of these parameters may be NULL. readfds contains file descriptors from which the process reads data, writefds contains file descriptors to which the process writes, and exceptfds contains exception file descriptors (it's usually ignored). Use the following macros to manipulate these structs easily: FD_ZERO (fd_set *fds) -- Empties fds. FD_SET(int fd, fd_set* fds) -- Adds fd to fds. FD_CLR(int fd, fd_set* fds) -- Removes fd from fds. FD_ISSET(int fd, fd_set* fds) -- Returns true if fd is contained in fds. The last parameter indicates how long select() should wait for an event. If it's NULL, then select() will block until an event occurs. When select() returns, readfds, writefds, and exceptfds contain the file descriptors that have input pending, that are ready to be written to, and that are in an exceptional condition. The return value is the total number of file descriptors contained in these sets, 0 if the call timed out or -1 if an error occurred. As select() modifies the sets passed to it, you should copy them to a different set before each call. The following program reads from two pipes "p1" and "p2" using select(): #include #include #include #include #include int main() { int fds[2]; /*file descriptors to watch*/ char buf[1024]={0}; int i, highestfd; fd_set readset; /*updated by select*/ fd_set stableset;/*for restoring readset after select()*/ /*open both pipes for read. For the sake of brevity, runtime errors aren't checked here*/ fds[0]=open("p1", O_RDONLY | O_NONBLOCK); fds[1]=open("p2", O_RDONLY | O_NONBLOCK); FD_ZERO(&stableset); /*add descriptors to set*/ FD_SET(fds[0], &stableset); FD_SET(fds[1], &stableset); /*find the max descriptor value*/ highestfd = fds[0] > fds[1] ? fds[0] : fds[1]; /*as long as at least one descriptor is being watched*/ while (FD_ISSET(fds[0], &stableset) || FD_ISSET(fds[1], &stableset) ) { readset=stableset; /*reconstitute original set*/ if(select(highestfd+1, &readset, NULL, NULL, NULL)<0) { /*handle errors and exit*/ } /*loop through files that have input pending*/ for (i=0; i<2; i++) { if FD_ISSET(fds[i], &readset) read(fds[i], buf, sizeof(buf)-1); } } /*...cleanup */ }
What’s wrong? The new clean desk test
Join the discussion
Be the first to comment on this article. Our Commenting Policies