Select (Unix)

select is a system call and application programming interface (API) in Unix-like and POSIX-compliant operating systems for examining the status of file descriptors of open input/output channels. The select system call is similar to the "poll" facility introduced in UNIX System V and later operating systems. However, with the c10k problem, both select and poll have been superseded by the likes of kqueue, epoll, /dev/poll and I/O completion ports.
One common use of select outside of its stated use of waiting on filehandles is to implement a portable sub-second sleep. This can be achieved by passing NULL for all three fd_set arguments, and the duration of the desired sleep as the timeout argument.
In the C programming language, the select system call is declared in the header file sys/select.h or unistd.h, and has the following syntax:
int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *errorfds, struct timeval *timeout);
codice_1 arguments may be manipulated with four utility macros: FD_SET(), FD_CLR(), FD_ZERO(), and FD_ISSET().
Select returns the total number of bits set in readfds, writefds and errorfds, or zero if the timeout expired, and -1 on error.
The sets of file descriptor used in select are finite in size, depending on the operating system. The newer system call "poll" provides a more flexible solution.
Example.
/* function prototypes */
void die(const char*);
int main(int argc, char **argv)
 int sockfd, new, maxfd, on = 1, nready, i;
 struct addrinfo *res0, *res, hints;
 char buffer[BUFSIZ];
 fd_set master, readfds;
 int error;
 ssize_t nbytes;
 (void)memset(&hints, '\0', sizeof(struct addrinfo));
 hints.ai_family = AF_INET;
 hints.ai_socktype = SOCK_STREAM;
 hints.ai_protocol = IPPROTO_TCP;
 hints.ai_flags = AI_PASSIVE;
 if (0 != (error = getaddrinfo(NULL, PORT, &hints, &res0)))
 errx(EXIT_FAILURE, "%s", gai_strerror(error));
 for (res = res0; res; res = res->ai_next)
 if (-1 == (sockfd = socket(res->ai_family, res->ai_socktype, res->ai_protocol)))
 perror("socket()");
 continue;
 if (-1 == (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, (char*)&on, sizeof(int))))
 perror("setsockopt()");
 continue;
 if (-1 == (bind(sockfd, res->ai_addr, res->ai_addrlen)))
 perror("bind()");
 continue;
 break;
 if (-1 == sockfd)
 exit(EXIT_FAILURE);
 freeaddrinfo(res0);
 if (-1 == (listen(sockfd, 32)))
 die("listen()");
 if (-1 == (fcntl(sockfd, F_SETFD, O_NONBLOCK)))
 die("fcntl()");
 FD_ZERO(&master);
 FD_ZERO(&readfds);
 FD_SET(sockfd, &master);
 maxfd = sockfd;
 while (1)
 memcpy(&readfds, &master, sizeof(master));
 (void)printf("running select()\n");
 if (-1 == (nready = select(maxfd+1, &readfds, NULL, NULL, NULL)))
 die("select()");
 (void)printf("Number of ready descriptor: %d\n", nready);
 for (i=0; i<=maxfd && nready>0; i++)
 if (FD_ISSET(i, &readfds))
 nready--;
 if (i == sockfd)
 (void)printf("Trying to accept() new connection(s)\n");
 if (-1 == (new = accept(sockfd, NULL, NULL)))
 if (EWOULDBLOCK != errno)
 die("accept()");
 break;
 else
 if (-1 == (fcntl(new, F_SETFD, O_NONBLOCK)))
 die("fcntl()");
 FD_SET(new, &master);
 if (maxfd < new)
 maxfd = new;
 else
 (void)printf("recv() data from one of descriptors(s)\n");
 nbytes = recv(i, buffer, sizeof(buffer), 0);
 if (nbytes <= 0)
 if (EWOULDBLOCK != errno)
 die("recv()");
 break;
 buffer[nbytes] = '\0';
 printf("%s", buffer);
 (void)printf("%zi bytes received.\n", nbytes);
 close(i);
 FD_CLR(i, &master);
 return 0;
void die(const char *msg)
 perror(msg);
 exit(EXIT_FAILURE);