内容简介
/* According to POSIX.1-2001 */ #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) void FD_CLR(int fd, fd_set *set) int FD_ISSET(int fd, fd_set *set) void FD_SET(int fd, fd_set *set) void FD_ZERO(fd_set *set) #define _XOPEN_SOURCE 600 #include <sys/select.h> int pselect(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, const struct timespec *timeout, const sigset_t *sigmask) |
描述
select() and%uA0pselect() 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.,%uA0read(2)) without blocking.The operation of%uA0select() and%uA0pselect() is identical, with three differences:
标签 | 描述 |
---|---|
(i) | select() uses a timeout that is a%uA0struct timeval%uA0(with seconds and microseconds), while%uA0pselect() uses a%uA0struct timespec%uA0(with seconds and nanoseconds). |
(ii) | select() may update the%uA0timeout%uA0argument to indicate how much time was left.%uA0pselect() does not change this argument. |
(iii) | select() has no%uA0sigmask%uA0argument, and behaves as%uA0pselect() called with NULL%uA0sigmask. |
Four macros are provided to manipulate the sets.%uA0FD_ZERO() clears a set.%uA0FD_SET() and%uA0FD_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%uA0select() returns.
nfds%uA0is the highest-numbered file descriptor in any of the three sets, plus 1.
timeout%uA0is an upper bound on the amount of time elapsed before%uA0select() returns. It may be zero, causing%uA0select() to return immediately. (This is useful for polling.) Iftimeout%uA0is NULL (no timeout),%uA0select() can block indefinitely.
sigmask%uA0is a pointer to a signal mask (see%uA0sigprocmask(2)) if it is not NULL, thenpselect() first replaces the current signal mask by the one pointed to by%uA0sigmask, then does the ‘select’ function, and then restores the original signal mask.
Other than the difference in the precision of the%uA0timeout%uA0argument, the followingpselect() call:
ready = pselect(nfds, &readfds, &writefds, &exceptfds, timeout, &sigmask) |
sigset_t origmask
sigprocmask(SIG_SETMASK, &sigmask, &origmask) |
The reason that%uA0pselect() is needed is that if one wants to wait for either a signal or for a file descriptor to become ready, then an atomic test is needed to prevent race conditions. (Suppose the signal handler sets a global flag and returns. Then a test of this global flag followed by a call of%uA0select() could hang indefinitely if the signal arrived just after the test but just before the call. By contrast,%uA0pselect() allows one to first block signals, handle the signals that have come in, then call%uA0pselect() with the desiredsigmask, avoiding the race.)
超时
The time structures involved are defined in%uA0<sys/time.h>%uA0and look like
struct timeval { long tv_sec /* seconds */ long tv_usec /* microseconds */ } |
and
struct timespec { long tv_sec /* seconds */ long tv_nsec /* nanoseconds */ } |
(However, see below on the POSIX.1-2001 versions.)
Some code calls%uA0select() with all three sets empty,%uA0n%uA0zero, and a non-NULL%uA0timeout%uA0as a fairly portable way to sleep with subsecond precision.
On Linux,%uA0select() modifies%uA0timeout%uA0to reflect the amount of time not slept most other implementations do not do this. (POSIX.1-2001 permits either behaviour.) This causes problems both when Linux code which reads%uA0timeout%uA0is ported to other operating systems, and when code is ported to Linux that reuses a struct timeval for multipleselect()s in a loop without reinitializing it. Consider%uA0timeout%uA0to be undefined afterselect() returns.
返回值
On success,%uA0select() and%uA0pselect() return the number of file descriptors contained in the three returned descriptor sets (that is, the total number of bits that are set in%uA0readfds,writefds,%uA0exceptfds) which may be zero if the timeout expires before anything interesting happens. On error, -1 is returned, and%uA0errno%uA0is set appropriately the sets and%uA0timeoutbecome undefined, so do not rely on their contents after an error.错误
标签 | 描述 |
---|---|
EBADF | An invalid file descriptor was given in one of the sets. (Perhaps a file descriptor that was already closed, or one on which an error has occurred.) |
EINTR | A signal was caught. |
EINVAL | nfds%uA0is negative or the value contained within%uA0timeout%uA0is invalid. |
ENOMEM | unable to allocate memory for internal tables. |
EXAMPLE
#include <stdio.h> #include <sys/time.h> #include <sys/types.h> #include <unistd.h> int main(void) { fd_set rfds struct timeval tv int retval /* Watch stdin (fd 0) to see when it has input. */ FD_ZERO(&rfds) FD_SET(0, &rfds) /* Wait up to five seconds. */ tv.tv_sec = 5 tv.tv_usec = 0 retval = select(1, &rfds, NULL, NULL, &tv) /* Don’t rely on the value of tv now! */
if (retval == -1)
return 0 |
遵循于
select() conforms to POSIX.1-2001 and 4.4BSD (select() first appeared in 4.2BSD). Generally portable to/from non-BSD systems supporting clones of the BSD socket layer (including System V variants). However, note that the System V variant typically sets the timeout variable before exit, but the BSD variant does not.pselect() is defined in POSIX.1g, and in POSIX.1-2001.
注意
An%uA0fd_set%uA0is a fixed size buffer. Executing%uA0FD_CLR() or%uA0FD_SET() with a value of%uA0fd%uA0that is negative or is equal to or larger than FD_SETSIZE will result in undefined behavior. Moreover, POSIX requires%uA0fd%uA0to be a valid file descriptor.Concerning the types involved, the classical situation is that the two fields of a%uA0timevalstructure are longs (as shown above), and the structure is defined in%uA0<sys/time.h>. The POSIX.1-2001 situation is
struct timeval { time_t tv_sec /* seconds */ suseconds_t tv_usec /* microseconds */ } |
where the structure is defined in%uA0<sys/select.h>%uA0and the data types%uA0time_t%uA0andsuseconds_t%uA0are defined in%uA0<sys/types.h>.
Concerning prototypes, the classical situation is that one should include%uA0<time.h>%uA0forselect(). The POSIX.1-2001 situation is that one should include%uA0<sys/select.h>%uA0forselect() and%uA0pselect(). Libc4 and libc5 do not have a%uA0<sys/select.h>%uA0header under glibc 2.0 and later this header exists. Under glibc 2.0 it unconditionally gives the wrong prototype for%uA0pselect(), under glibc 2.1-2.2.1 it gives%uA0pselect() when%uA0_GNU_SOURCE%uA0is defined, under glibc 2.2.2-2.2.4 it gives it when%uA0_XOPEN_SOURCE%uA0is defined and has a value of 600 or larger. No doubt, since POSIX.1-2001, it should give the prototype by default.
版本
pselect() was added to Linux in kernel 2.6.16. Prior to this,%uA0pselect() was emulated in glibc (but see BUGS).LINUX 注意
The Linux%uA0pselect() system call modifies its%uA0timeout%uA0argument. However, the glibc wrapper function hides this behaviour by using a local variable for the timeout argument that is passed to the system call. Thus, the glibc%uA0pselect() function does not modify its timeout argument this is the behaviour required by POSIX.1-2001.BUGS
Glibc 2.0 provided a version of%uA0pselect() that did not take a%uA0sigmask%uA0argument.Since version 2.1, glibc has provided an emulation of%uA0pselect() that is implemented using%uA0sigprocmask(2) and%uA0select(). This implementation remains vulnerable to the very race condition that%uA0pselect() was designed to prevent. On systems that lack%uA0pselect() reliable (and more portable) signal trapping can be achieved using the self-pipe trick (where a signal handler writes a byte to a pipe whose other end is monitored byselect() in the main program.)
Under Linux,%uA0select() may report a socket file descriptor as "ready for reading", while nevertheless a subsequent read blocks. This could for example happen when data has arrived but upon examination has wrong checksum and is discarded. There may be other circumstances in which a file descriptor is spuriously reported as ready. Thus it may be safer to use O_NONBLOCK on sockets that should not block.
另请参阅
For vaguely related stuff, see%uA0accept(2),%uA0connect(2),%uA0poll(2),%uA0read(2),%uA0recv(2),%uA0send(2),sigprocmask(2),%uA0write(2),%uA0epoll(7),%uA0feature_test_macros(7)%uA0