select 不仅会改变timeout的值,而且会改变fd_set集合的值。所以调用完一次select后,fd_set和timeout都必须重置.
On Linux, select() modifies timeout to reflect the amount of time not slept; most other implementations do not do this. (POSIX.1-2001 permits either behavior.) This causes problems both when Linux code which reads timeout is ported to other operating systems, and when code is ported to Linux that reuses a struct timeval for multiple select()s in a loop without reinitializing it. Consider timeout to be undefined after select() returns.
struct timeval {
long tv_sec; /* seconds */
long tv_usec; /* microseconds */
};
#include <sys/select.h>
/* According to earlier standards */
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
int select(int nfds, fd_set *readfds, fd_set *writefds,fd_set *exceptfds, struct timeval *timeout);
DESCRIPTION
select() and pselect() allow a program to monitor multiple file descriptors, waiting until one or more of the file descriptors become "ready" for some
class of I/O operation (e.g., input possible). A file descriptor is considered ready if it is possible to perform the corresponding I/O operation (e.g.,
read(2)) without blocking.
The operation of select() and pselect() is identical, with three differences:
void FD_CLR(int fd, fd_set *set); //将fd从文件描述符集合中删除
int FD_ISSET(int fd, fd_set *set);//判断fd是否在文件描述符集合中
void FD_SET(int fd, fd_set *set);//将fd加入到文件描述符集合中
void FD_ZERO(fd_set *set); // 文件描述符集清零
Four macros are provided to manipulate the sets. FD_ZERO() clears a set. FD_SET() and FD_CLR() respectively add and remove a given file descriptor from a
set. FD_ISSET() tests to see if a file descriptor is part of the set; this is useful after select() returns.
nfds is the highest-numbered file descriptor in any of the three sets, plus 1.
timeout is an upper bound on the amount of time elapsed before select() returns. If both fields of the timeval structure are zero, then select() returns
immediately. (This is useful for polling.) If timeout is NULL (no timeout), select() can block indefinitely.
用法举例:
fd_set fds;
struct
timeval timeout;
FD_ZERO(&fds);
FD_SET(pip[0], &fds);
timeout.tv_sec = 5;
timeout.tv_usec = 0;
ret = select(pip[0]+1, &fds, NULL, NULL, &timeout);
此外, select 还可以用于延时, 不过真搞不明白为啥不用usleep/sleep, 非得要用这么费周折的用法。
Some code calls select() with all three sets empty, nfds zero, and a non-NULL timeout as a fairly portable way to sleep with subsecond precision.
void
sleep_select(
int
i)
{
struct
timeval timeout;
timeout.tv_sec = i;
timeout.tv_usec = 0;
select(0, NULL, NULL, NULL, &timeout);
}