|
|||||
| | |||||
The select function call allows a process to wait on multiple file descriptors simultanously with an optional timeout. The select() call will return as soon as it is possible to perform operations on any of the indicated file descriptors. This allows a process to perform some basic multi-tasking without forking another process or starting another thread.
It also does not hogtie the CPU. the CPU is hogtied when using blocking IO such as the following:
blocking I/O means the use of the cpu is BLOCKED
while (( z= read(fd, buf, sizeof buf)) == -1 && errno==EAGAIN) ;
instead, we want to relinquish the CPU for a little while
So, it used whenever there are sub-processes (each with a file descriptor -- i don't think these are really called file descriptors). For example, FIFO pipes created with popen("ls","r");
while we are here, other ways to go around blocking IO are:
return values:
basic strategy: note that simple examples, will do the FD_* macros, issue a simple select which reads from a fd or socket-fd, then issue a read/write or exit. Anything more practical will undoubtedly be involved in multiple read/write loops. Thus a skeleton implementation is here:
do {
FD_ZERO....
FD_SET....
WRONG: (while ((rv = select() > 0) {
RIGHT: while (( rv = select() == -1 && errno=EINTR) ....
if (rv == -1) quit;
if (rv == 0 ) // timeout; handle how see fit
if (FD_ISSET .... and query all file descriptors in the fd_sets.
}
sometimes teh above is implemented using for(;;)
the purpose of the loop is to, like I said, to multiple reads/writes as in any application, server or client, but we need simultaneously to reinitialize the FD_ macros.
there is a sequence of steps for interacting with sockets and the select call
| server | client |
| fd = socket() | NA |
| listen(fd) | NA |
| NA | connect |
| triggers read event, so server must then call accept | NA |
| read | NA |
| NA | EOF/closed socket |
| NA | NA |
| Leave a Reply |