CIS 307: Unix III
Select is a complex service:
#include <sys/types.h>
#include <sys/time.h>
int select(
int nfds, /* Number of objects monitored*/
fd_set *readfds, /* Set of file descriptors open for reading*/
fd_set *writefds, /* Set of file descript. open for writing*/
fd_set *exceptfds, /* Set of file descript. with exception pending*/
struct timeval *timout); /* Structure specifying timeout */
If timout is null, then we block until one of the fd objects
becomes ready. If timout points to a structure with timeout
equal to 0, then we do not block at all. Otherwise we will block
up to the time specified by timout.
FD_ZERO(&fdset) /* fdset becomes the empty set */
FD_SET(fd,&fdset) /* fd is added to fdset */
FD_CLR(fd,&fdset) /* fd is removed from fdset */
FD_ISSET(fd,&fdset) /* it determines if fd is in fdset */
The structure timeval, defined in sys/time.h is
struct timeval { int tv_sec; /* second */
int tv_usec;} /* microseconds */
Here are three examples of use of select. The first is a simple program from Stevens for determining the maximum size for a pipe. [When run on my alpha the program prints that the size is 65536.]
#include <sys/types.h>
#include <sys/time.h>
int main(void)
{
int i, n, fd[2];
fd_set writeset;
struct timeval tv;
if (pipe(fd) < 0){
perror("pipe");
exit(1);}
FD_ZERO(&writeset); /* set to zero the writeset */
for (n = 0; ; n++) { /* write 1 byte at a time until pipe is full */
FD_SET(fd[1], &writeset); /*add write-end of pipe to writeset*/
tv.tv_sec = tv.tv_usec = 0; /* don't wait at all */
/* select returns the number of objects (in readset, */
/* writeset, or exceptionset) that are ready. */
/* In our case there will be at most one ready object.*/
if ( (i = select(fd[1]+1, NULL, &writeset, NULL, &tv)) < 0) {
perror("select");
exit(1);}
else if (i == 0) /*We cannot write to pipe, i.e. it is full*/
break;
if (write(fd[1], "a", 1) != 1){
perror("write error");
exit(1);}
}
printf("pipe capacity = %d\n", n);
exit(0);
}
The second is a program also from Stevens for waiting on a timer.
#include <sys/types.h>
#include <sys/time.h>
main(argc, argv)
int argc;
char *argv[];
{
long atol();
static struct timeval timeout;
if (argc != 3) {
printf("usage: timer <#seconds> <#microseconds>");
exit(1);}
timeout.tv_sec = atol(argv[1]);
timeout.tv_usec = atol(argv[2]);
/* selet blocks waiting for the timeout to expire. */
if (select(0, (fd_set *) 0, (fd_set *) 0, (fd_set *) 0, &timeout) < 0){
perror("select error");
exit(1);}
exit(0);
}
The third is a simple program where a process reads fixed size messages from two pipes. You should terminate the program from the terminal with a CONTROL-C.
#include <sys/types.h>
#include <sys/time.h>
#include <unistd.h>
#include <stdio.h>
#define MAXLINE 12
int main(void)
{
int i, m, n;
int fd1[2]; /* pipe for communications from child1 to parent */
int fd2[2]; /* pipe for communications from child2 to parent */
pid_t pid;
char line[MAXLINE];
fd_set readset;
static struct timeval timeout;
if (pipe(fd1) < 0) {
perror("pipe1");
exit(1);}
if (pipe(fd2) < 0) {
perror("pipe2");
exit(1);}
/* child1 */
if ( (pid = fork()) < 0) {
perror("fork1");
exit(1);}
else if (pid == 0) {
close(fd1[0]);
while (1) {
write(fd1[1], "from child1\n", MAXLINE);
sleep(1);}
exit(0);}
/* child2 */
if ( (pid = fork()) < 0) {
perror("fork2");
exit(1);}
else if (pid == 0) {
close(fd2[0]);
while (1) {
write(fd2[1], "from child2\n", MAXLINE);
sleep(1.3);}
exit(0);}
/* parent */
close(fd1[1]);
close(fd2[1]);
m = 1 + ((fd1[0]<fd2[0])?fd2[0]:fd1[0]); /*Max # of objs to wait for*/
FD_ZERO(&readset);
while (1) {
FD_SET(fd1[0], &readset);
FD_SET(fd2[0], &readset);
if (select(m,&readset, NULL,NULL,NULL) < 0) {
perror("select");
exit(1);}
if (FD_ISSET(fd1[0], &readset)) {
n = read(fd1[0], line, MAXLINE);
write(STDOUT_FILENO, line, n);}
if (FD_ISSET(fd2[0], &readset)) {
n = read(fd2[0], line, MAXLINE);
write(STDOUT_FILENO, line, n);}
}
exit(0);
}
Note that in a more realistic program we will deal with messages that are
of variable sizes and more than two pipes (thinking of how you would
deal with many file descriptors without having to increase the size of
your program? can you also think of ways to be fair to the message sources?)
There will be other occasions to see select, in action.
ingargiola.cis.temple.edu