FD_SETのヘルプ・マニュアル
日本語 英語
FD_SET --help
man FD_SET
SELECT(2) Linux Programmer’s Manual SELECT(2)
名前
select, pselect, FD_CLR, FD_ISSET, FD_SET, FD_ZERO - 多重化された I/O
の同期をとる
書式
/* POSIX.1-2001 に従う場合 */
#include
/* 以前の規格に従う場合 */
#include
#include
#include
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);
#include
int pselect(int nfds, fd_set *readfds, fd_set *writefds,
fd_set *exceptfds, const struct timespec *timeout,
const sigset_t *sigmask);
glibc 向けの機能検査マクロの要件 (feature_test_macros(7) 参照):
pselect(): _POSIX_C_SOURCE >= 200112L || _XOPEN_SOURCE >= 600
説明
select() や pselect() を使うと、プログラムで複数のファイルディスクリ プ
タ を 監 視 し 、 一つ以上のファイルディスクリプタがある種の I/O 操作の
「ready (準備ができた)」状態 (例えば、読み込み可能になった状態) にな る
ま で待つことができる。ファイルディスクリプタが ready (準備ができた) と
は、対応する I/O 操作 (例えば read(2) など) が停止 (block) なしに実行可
能な状態にあることを意味する。
select() と pselect() の動作は同じであるが、以下の 3 点が異なる:
(i) select() では、タイムアウト時間の指定に構造体 struct timeval (秒
・マイクロ秒単位) を用いる。一方、 pselect() 関数では、 構 造 体
struct timespec (秒・ナノ秒単位) を用いる。
(ii) select() は残り時間を示す timeout 引き数を更新することがある。
pselect() はこの引き数を変更しない。
(iii) select() は sigmask 引き数を持たない。その動作は sigmask に NULL
を指定した場合の pselect() と同じである。
3 つの独立したファイルディスクリプタ集合の監視を行う。 readfds に入れら
れたディスクリプタについては、読み込みが可能かどうかを監視する (より 正
確にいうと、停止 (block) なしで読むことができるかを調べる。ファイルの終
端 (end-of-file) の場合も、ファイルディスクリプタは読み込み可能として扱
われる)。 writefds に入れられたディスクリプタについては、停止せずに書き
込みが可能かどうかを監視する。 exceptfds にあるものについては、例外の監
視 を行なう。システムコール終了時に、どのファイルディスクリプタの状態が
実際に変化したか示すために、集合の内容が変更される。ある種別のイベン ト
を 監視したいファイルディスクリプタが一つもない場合には、対応するファイ
ルディスクリプタ集合に NULL を指定することができる。
集合を操作するために 4 つのマクロが提供されている。 FD_ZERO() は集合 を
消 去する。 FD_SET() と FD_CLR() はそれぞれ指定したファイルディスクリプ
タの集合への追加、削除を行う。 FD_ISSET() は集合にファイルディスクリ プ
タ があるかどうか調べる; このマクロは select() が終了した後に使うと便利
である。
nfds は 3 つの集合に含まれるファイルディスクリプタの最大値に 1 を足した
ものである。
timeout は select() が復帰するまでの経過時間の上限である。 timeval 構造
体の両方のフィールドが 0 の場合、 select() はすぐに復帰する (この機能は
ポ ーリング (polling) を行うのに便利である)。 timeout に NULL (タイムア
ウトなし) が指定されると、 select() は無期限に停止 (block) する。
sigmask は、シグナルマスク (sigprocmask(2) を参照) へのポインタである。
sigmask が NULL でない場合、 pselect() は sigmask が指しているシグナル
マスクで現在のシグナルマスクを置き換えてから、 "select" 関数を実行し 、
終了後にシグナルマスクを元のシグナルマスクに戻す。
timeout 引き数の精度の違いを除くと、以下の pselect() の呼び出しは、
ready = pselect(nfds, &readfds, &writefds, &exceptfds,
timeout, &sigmask);
次のコールを atomic に実行するのと等価である。
sigset_t origmask;
sigprocmask(SIG_SETMASK, &sigmask, &origmask);
ready = select(nfds, &readfds, &writefds, &exceptfds, timeout);
sigprocmask(SIG_SETMASK, &origmask, NULL);
pselect() が必要になる理由は、シグナルやファイルディスクリプタの状態変
化を待ちたいときには、競合状態を避けるために atomic なテストが必要に な
る からである。 (シグナルハンドラが大域フラグを設定して戻る場合を考えて
みよう。この大域フラグのテストに続けて select() を呼び出すと、シグナ ル
が テストの直後かつ呼び出しの直前に届いた時には select() は永久にハング
してしまうかもしれない。一方、 pselect() を使うと、まずシグナルを 禁 止
(block) して、入ってくるシグナルを操作し、望みの sigmask で pselect()
を呼び出すことで、前記の競合を避けることができる。)
タイムアウト
これらの関数で使用される時間関連の構造体は、 で以下のよ う
に定義されている。
struct timeval {
long tv_sec; /* 秒 */
long tv_usec; /* マイクロ秒 */
};
struct timespec {
long tv_sec; /* 秒 */
long tv_nsec; /* ナノ秒 */
};
(POSIX.1-2001 での定義については下記の「注意」を参照)
秒単位以下の精度でスリープを実現する移植性の高い方法として、 3 つの集合
全てを空、 nfds を 0 、 timeout を NULL でない値に設定して select() を
呼び出すという方法を使っているコードもある。
Linux では、 select() は timeout を変更し、残りの停止時間を反映するよう
になっているが、他のほとんどの実装では こ の よ う に な っ て い な い
(POSIX.1-2001 はどちらの動作も認めている)。このため、 timeout を参照し
ている Linux のコードを他のオペレーティング・システムへ移植する場合、問
題が起こる。また、ループの中で timeval 構造体を初期化せずにそのまま再利
用して select() を複数回行なっているコードを Linux へ移植する場合にも、
問題が起こる。 select() から復帰した後は timeout は未定義であると考える
べきである。
返り値
成功した場合、 select() と pselect() は更新された 3 つのディスクリプ タ
集 合 に 含 ま れ て い るファイルディスクリプタの数 (つまり、 readfds,
writefds, exceptfds 中の 1 になっているビットの総数) を返す。何も起こら
ずに時間切れになった場合、ディスクリプタの数は 0 になることもある。エラ
ーならば -1 を返し、 errno に適切な値が設定される; 集合と timeout は 未
定義となるので、エラーが起こった後はそれらの内容を信頼してはならない。
エラー
EBADF いずれかの集合に無効なファイルディスクリプタが指定された (おそら
くは、すでにクローズされたファイルディスクリプタか、エラーが発生
したファイルディスクリプタが指定された)。
EINTR シグナルを受信した。
EINVAL n が負、または timeout に入っている値が不正である。
ENOMEM 内部テーブルにメモリを割り当てることができなかった。
バージョン
pselect() は カーネル 2.6.16 で Linux に追加された。それ以前は、 pse-
lect() は glibc でエミュレートされていた (「バグ」の章を参照)。
準拠
select() は POSIX.1-2001 と 4.4BSD (select() は 4.2BSD で最初に登 場 し
た) に準拠する。 BSD ソケット層のクローンをサポートしている非 BSD シス
テム (System V 系も含む) との間でだいたい移植性がある。しかし System V
系 ではたいがい timeout 変数を exit の前にセットするが、 BSD 系ではそう
でないので注意すること。
pselect() は POSIX.1g と POSIX.1-2001 で定義されている。
注意
fd_set は固定サイズのバッファである。負や FD_SETSIZE 以上の値を持つ fd
に 対して FD_CLR() や FD_SET() を実行した場合、どのような動作をするかは
定義されていない。また、 POSIX では fd は有効なファイルディスクリプタで
なければならないと規定されている。
型 宣言に関しては、昔ながらの状況では timeval 構造体の 2 つのフィールド
は (上記のように) 両方とも long 型であり、構造体は で定 義
されている。 POSIX.1-2001 の下では、以下のようになっている。
struct timeval {
time_t tv_sec; /* 秒 */
suseconds_t tv_usec; /* マイクロ秒 */
};
この構造体は で定義されており、データ型 time_t と susec-
onds_t は で定義されている。
プロトタイプに関しては、昔ながらの状況で select() を使いたい場 合 は 、
をインクルードすればよい。 POSIX.1-2001 の環境で select() と
pselect() を使いたい場合は、 をインクルードすればよい。
ヘッダファイル は libc4 と libc5 にはなく、glibc 2.0 以
降 に存在する。悪いことに glibc 2.0 以前では pselect() のプロトタイプが
間違っている。 glibc 2.1 から 2.2.1 では _GNU_SOURCE が定義されている場
合に、 pselect() が提供される。 glibc 2.2.2 以降では、 pselect() を使用
するには、「書式」に記載された要件を満たす必要がある。
Linux での注意
Linux の pselect() システムコールは timeout 引き数を変更する。しかし 、
glibc のラッパー関数は、システムコールに渡す timeout 引き数としてローカ
ル変数を使うことでこの動作を隠蔽している。このため、glibc の pselect()
関数は timeout 引き数を変更しない。これが POSIX.1-2001 が要求している動
作である。
バグ
glibc 2.0 では、 sigmask 引き数を取らないバージョンの pselect() が提 供
されていた。
バ ー ジ ョ ン 2.1 以降の glibc では、 pselect() は sigprocmask(2) と
select() を使ってエミュレートされていた。この実装にはきわどい競合条件に
おいて脆弱性が残っている。この競合条件における問題を防止するために pse-
lect() は設計されたのである。 pselect() がないシステムにおいて、シグ ナ
ルの捕捉を信頼性があり (移植性も高い) 方法で行うには、自己パイプ (self-
pipe) という技を使うとよい (シグナルハンドラはパイプへ 1 バイトのデータ
を 書き込み、同じパイプのもう一端をメインプログラムの select() で監視す
るという方法である)。
Linux では、 select() がソケットファイルディスクリプタで "読み込みの 準
備ができた" と報告した場合でも、この後で read を行うと停止 (block) する
ことがある。このような状況は、例えば、データが到着したが、検査でチェ ッ
ク サム異常が見つかり廃棄された時などに起こりえる。他にもファイルディス
クリプタが準備できたと間違って報告される状況が起こるかもしれない。し た
が って、停止すべきではないソケットに対しては O_NONBLOCK を使うとより安
全であろう。
Linux では、 select() がシグナルハンドラにより割り込まれた場合 (つま り
EINTR エラーが返る場合)、 timeout も変更する。これは POSIX.1-2001 では
認められていない挙動である。 Linux の pselect() システムコールも同じ 挙
動 を するが、 glibc のラッパー関数がこの挙動を隠蔽している。具体的には
、glibc のラッパー関数の内部で、 timeout をローカル変数にコピーし、この
ローカル変数をシステムコールに渡している。
例
#include
#include
#include
#include
#include
int
main(void)
{
fd_set rfds;
struct timeval tv;
int retval;
/* stdin (fd 0) を監視し、入力があった場合に表示する。*/
FD_ZERO(&rfds);
FD_SET(0, &rfds);
/* 5 秒間監視する。*/
tv.tv_sec = 5;
tv.tv_usec = 0;
retval = select(1, &rfds, NULL, NULL, &tv);
/* この時点での tv の値を信頼してはならない。*/
if (retval == -1)
perror("select()");
else if (retval)
printf("今、データが取得できました。\n");
/* FD_ISSET(0, &rfds) が true になる。*/
else
printf("5 秒以内にデータが入力されませんでした。\n");
exit(EXIT_SUCCESS);
}
関連項目
考察と使用例の書かれたチュートリアルとして、 select_tut(2) がある。
関 係 が あ り そ うなものを挙げておく: accept(2), connect(2), poll(2),
read(2), recv(2), send(2), sigprocmask(2), write(2), epoll(7), time(7)
Linux 2008-12-05 SELECT(2)
SELECT(2) Linux Programmer’s Manual SELECT(2)
NAME
select, pselect, FD_CLR, FD_ISSET, FD_SET, FD_ZERO - synchronous I/O
multiplexing
SYNOPSIS
/* According to POSIX.1-2001 */
#include
/* According to earlier standards */
#include
#include
#include
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);
#include
int pselect(int nfds, fd_set *readfds, fd_set *writefds,
fd_set *exceptfds, const struct timespec *timeout,
const sigset_t *sigmask);
Feature Test Macro Requirements for glibc (see feature_test_macros(7)):
pselect(): _POSIX_C_SOURCE >= 200112L || _XOPEN_SOURCE >= 600
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 corre-
sponding I/O operation (e.g., read(2)) without blocking.
The operation of select() and pselect() is identical, with three dif-
ferences:
(i) select() uses a timeout that is a struct timeval (with seconds
and microseconds), while pselect() uses a struct timespec (with
seconds and nanoseconds).
(ii) select() may update the timeout argument to indicate how much
time was left. pselect() does not change this argument.
(iii) select() has no sigmask argument, and behaves as pselect()
called with NULL sigmask.
Three independent sets of file descriptors are watched. Those listed
in readfds will be watched to see if characters become available for
reading (more precisely, to see if a read will not block; in particu-
lar, a file descriptor is also ready on end-of-file), those in writefds
will be watched to see if a write will not block, and those in
exceptfds will be watched for exceptions. On exit, the sets are modi-
fied in place to indicate which file descriptors actually changed sta-
tus. Each of the three file descriptor sets may be specified as NULL
if no file descriptors are to be watched for the corresponding class of
events.
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 stucture are zero, then
select() returns immediately. (This is useful for polling.) If time-
out is NULL (no timeout), select() can block indefinitely.
sigmask is a pointer to a signal mask (see sigprocmask(2)); if it is
not NULL, then pselect() first replaces the current signal mask by the
one pointed to by sigmask, then does the "select" function, and then
restores the original signal mask.
Other than the difference in the precision of the timeout argument, the
following pselect() call:
ready = pselect(nfds, &readfds, &writefds, &exceptfds,
timeout, &sigmask);
is equivalent to atomically executing the following calls:
sigset_t origmask;
sigprocmask(SIG_SETMASK, &sigmask, &origmask);
ready = select(nfds, &readfds, &writefds, &exceptfds, timeout);
sigprocmask(SIG_SETMASK, &origmask, NULL);
The reason that pselect() 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 select() could hang indefinitely if the sig-
nal arrived just after the test but just before the call. By contrast,
pselect() allows one to first block signals, handle the signals that
have come in, then call pselect() with the desired sigmask, avoiding
the race.)
The timeout
The time structures involved are defined in and 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 select() with all three sets empty, nfds zero, and a
non-NULL timeout as a fairly portable way to sleep with subsecond pre-
cision.
On Linux, select() modifies timeout to reflect the amount of time not
slept; most other implementations do not do this. (POSIX.1-2001 per-
mits 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.
RETURN VALUE
On success, select() and pselect() return the number of file descrip-
tors contained in the three returned descriptor sets (that is, the
total number of bits that are set in readfds, writefds, exceptfds)
which may be zero if the timeout expires before anything interesting
happens. On error, -1 is returned, and errno is set appropriately; the
sets and timeout become undefined, so do not rely on their contents
after an error.
ERRORS
EBADF An invalid file descriptor was given in one of the sets. (Per-
haps a file descriptor that was already closed, or one on which
an error has occurred.)
EINTR A signal was caught; see signal(7).
EINVAL nfds is negative or the value contained within timeout is
invalid.
ENOMEM unable to allocate memory for internal tables.
VERSIONS
pselect() was added to Linux in kernel 2.6.16. Prior to this, pse-
lect() was emulated in glibc (but see BUGS).
CONFORMING TO
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.
NOTES
An fd_set is a fixed size buffer. Executing FD_CLR() or FD_SET() with
a value of fd that is negative or is equal to or larger than FD_SETSIZE
will result in undefined behavior. Moreover, POSIX requires fd to be a
valid file descriptor.
Concerning the types involved, the classical situation is that the two
fields of a timeval structure are typed as long (as shown above), and
the structure is defined in . The POSIX.1-2001 situation
is
struct timeval {
time_t tv_sec; /* seconds */
suseconds_t tv_usec; /* microseconds */
};
where the structure is defined in and the data types
time_t and suseconds_t are defined in .
Concerning prototypes, the classical situation is that one should
include for select(). The POSIX.1-2001 situation is that one
should include for select() and pselect().
Libc4 and libc5 do not have a header; under glibc 2.0
and later this header exists. Under glibc 2.0 it unconditionally gives
the wrong prototype for pselect(). Under glibc 2.1 to 2.2.1 it gives
pselect() when _GNU_SOURCE is defined. Since glibc 2.2.2 the
requirements are as shown in the SYNOPSIS.
Linux Notes
The Linux pselect() system call modifies its timeout argument. How-
ever, the glibc wrapper function hides this behavior by using a local
variable for the timeout argument that is passed to the system call.
Thus, the glibc pselect() function does not modify its timeout argu-
ment; this is the behavior required by POSIX.1-2001.
BUGS
Glibc 2.0 provided a version of pselect() that did not take a sigmask
argument.
Since version 2.1, glibc has provided an emulation of pselect() that is
implemented using sigprocmask(2) and select(). This implementation
remains vulnerable to the very race condition that pselect() was
designed to prevent. On systems that lack pselect(), 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 by select() in the main program.)
Under Linux, select() 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.
On Linux, select() also modifies timeout if the call is interrupted by
a signal handler (i.e., the EINTR error return). This is not permitted
by POSIX.1-2001. The Linux pselect() system call has the same behav-
ior, but the glibc wrapper hides this behavior by internally copying
the timeout to a local variable and passing that variable to the system
call.
EXAMPLE
#include
#include
#include
#include
#include
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)
perror("select()");
else if (retval)
printf("Data is available now.\n");
/* FD_ISSET(0, &rfds) will be true. */
else
printf("No data within five seconds.\n");
exit(EXIT_SUCCESS);
}
SEE ALSO
For a tutorial with discussion and examples, see select_tut(2).
For vaguely related stuff, see accept(2), connect(2), poll(2), read(2),
recv(2), send(2), sigprocmask(2), write(2), epoll(7), time(7)
COLOPHON
This page is part of release 3.22 of the Linux man-pages project. A
description of the project, and information about reporting bugs, can
be found at http://www.kernel.org/doc/man-pages/.
Linux 2008-12-05 SELECT(2)