X-Git-Url: http://git.osdn.net/view?p=linuxjm%2FLDP_man-pages.git;a=blobdiff_plain;f=draft%2Fman2%2Fselect_tut.2;h=808ad8dcf26bb6bb1cc7964a7b27cdfd92615ec9;hp=50b71cfd03674e110e438dfb746af662742d9c2a;hb=83f9e5d087c3464d5131604d3c9893479e6228eb;hpb=b94f6942a04e90221e87f25451f3501870695e96 diff --git a/draft/man2/select_tut.2 b/draft/man2/select_tut.2 index 50b71cfd..808ad8dc 100644 --- a/draft/man2/select_tut.2 +++ b/draft/man2/select_tut.2 @@ -82,44 +82,44 @@ glibc 向けの機能検査マクロの要件 (\fBfeature_test_macros\fP(7) 参 .sp \fBpselect\fP(): _POSIX_C_SOURCE\ >=\ 200112L || _XOPEN_SOURCE\ >=\ 600 .SH 説明 -\fBselect\fP() (や \fBpselect\fP()) を使うと、効率的に複数のファイルディスクリプタを監視し、 -そのファイルディスクリプタのいずれかが 「ready (準備ができた)」状態、つまり I/O (入出力) が可能になっているかや、 -ファイルディスクリプタのいずれかが 「例外状態 (exceptional condition)」が発生したか、を調べることができる。 +\fBselect\fP() (や \fBpselect\fP()) を使うと、効率的に複数のファイルディスクリプターを監視し、 +そのファイルディスクリプターのいずれかが 「ready (準備ができた)」状態、つまり I/O (入出力) が可能になっているかや、 +ファイルディスクリプターのいずれかが 「例外状態 (exceptional condition)」が発生したか、を調べることができる。 -この関数の主要な引き数は、3種類のファイルディスクリプタの「集合」 \fIreadfds\fP, \fIwritefds\fP, \fIexceptfds\fP である。 -各々の集合は \fBfd_set\fP として宣言され、その内容は \fBFD_CLR\fP(), \fBFD_ISSET\fP(), \fBFD_SET\fP(), +この関数の主要な引き数は、3種類のファイルディスクリプターの「集合」 \fIreadfds\fP, \fIwritefds\fP, \fIexceptfds\fP +である。 各々の集合は \fBfd_set\fP として宣言され、その内容は \fBFD_CLR\fP(), \fBFD_ISSET\fP(), \fBFD_SET\fP(), \fBFD_ZERO\fP() といったマクロによって操作できる。 新しく宣言された集合は、まず最初に \fBFD_ZERO\fP() を使ってクリアすべきである。 \fBselect\fP() はこれらの集合の内容を、以降に述べる規則に従って修正する。 \fBselect\fP() -を呼んだ後、ファイルディスクリプタがまだ集合に存在しているかどうかは、 \fBFD_ISSET\fP() マクロによって調べることができる。 -\fBFD_ISSET\fP() は指定されたディスクリプタが集合に存在していれば 0 以外の値を返し、 存在しなければ 0 を返す。 -\fBFD_CLR\fP() は集合からのファイルディスクリプタの削除を行う。 +を呼んだ後、ファイルディスクリプターがまだ集合に存在しているかどうかは、 \fBFD_ISSET\fP() マクロによって調べることができる。 +\fBFD_ISSET\fP() は指定されたディスクリプターが集合に存在していれば 0 以外の値を返し、 存在しなければ 0 を返す。 +\fBFD_CLR\fP() は集合からのファイルディスクリプターの削除を行う。 .SS 引き数 .TP \fIreadfds\fP -この集合に含まれるいずれかのファイルディスクリプタで、 データの読み込みが可能になったかどうかを監視する。 \fBselect\fP() -から戻る時に、\fIreadfds\fP のうち、 直ちに読み込み可能なファイルディスクリプタ以外は 集合から削除される。 +この集合に含まれるいずれかのファイルディスクリプターで、 データの読み込みが可能になったかどうかを監視する。 \fBselect\fP() +から戻る時に、\fIreadfds\fP のうち、 直ちに読み込み可能なファイルディスクリプター以外は 集合から削除される。 .TP \fIwritefds\fP -この集合に含まれるいずれかのファイルディスクリプタで、 データを書き込むスペースがあるかどうかを監視する。 \fBselect\fP() -から戻る時に、\fIwritefds\fP のうち、 直ちに書き込み可能なファイルディスクリプタ以外は 集合から削除される。 +この集合に含まれるいずれかのファイルディスクリプターで、 データを書き込むスペースがあるかどうかを監視する。 \fBselect\fP() +から戻る時に、\fIwritefds\fP のうち、 直ちに書き込み可能なファイルディスクリプター以外は 集合から削除される。 .TP \fIexceptfds\fP -この集合に含まれるいずれかのファイルディスクリプタで、 「例外状態 (exceptional condition)」が発生したかどうかを監視する。 +この集合に含まれるいずれかのファイルディスクリプターで、 「例外状態 (exceptional condition)」が発生したかどうかを監視する。 実際の動作では、普通に起こり得る例外状態は一つだけであり、 それは TCP ソケットで \fI帯域外 (out\-of\-band; OOB)\fP データが 読み込み可能な場合である。 OOB データの詳細については、 \fBrecv\fP(2), \fBsend\fP(2), \fBtcp\fP(7) を参照のこと。 (これ以外では、まれなことだが、 パケットモードの擬似端末 (pseudoterminals) で \fBselect\fP() が例外状態を示すことがある。) \fBselect\fP() が返る時に、\fIexceptfds\fP のうち、 -例外状態が発生したディスクリプタ以外は集合から削除される。 +例外状態が発生したディスクリプター以外は集合から削除される。 .TP \fInfds\fP -全ての集合に含まれるファイルディスクリプタのうち、 値が最大のものに 1 を足した整数である。 -すなわち、ファイルディスクリプタを各集合に加える作業の途中で、 全てのファイルディスクリプタを見て最大値を求め、 それに 1 を加えて \fInfds\fP -として渡さないといけない、ということだ。 +全ての集合に含まれるファイルディスクリプターのうち、 値が最大のものに 1 を足した整数である。 +すなわち、ファイルディスクリプターを各集合に加える作業の途中で、 全てのファイルディスクリプターを見て最大値を求め、 それに 1 を加えて +\fInfds\fP として渡さないといけない、ということだ。 .TP \fIutimeout\fP (何も起こらなかった場合に) \fBselect\fP() が戻る前に待つ最大時間である。 この値に NULL を渡すと、 \fBselect\fP() -はファイルディスクリプタのいずれかが ready (準備ができた) 状態に なるまで待ち続けてずっと停止する。 \fIutimeout\fP は 0 -秒にすることもでき、 この場合 \fBselect\fP() は直ちに返り、呼び出し時点のファイルディスクリプタの状態に 関する情報が返される。 構造体 +はファイルディスクリプターのいずれかが ready (準備ができた) 状態に なるまで待ち続けてずっと停止する。 \fIutimeout\fP は 0 +秒にすることもでき、 この場合 \fBselect\fP() は直ちに返り、呼び出し時点のファイルディスクリプターの状態に 関する情報が返される。 構造体 \fIstruct timeval\fP は次のように定義されている: .IP .in +4n @@ -150,15 +150,15 @@ struct timespec { \fBsigprocmask\fP(2) を参照)。 この引き数は NULL にすることもでき、その場合はこの関数へ 入るとき・出るときにシグナルマスクを変更しない。 この場合、 \fBpselect\fP() は \fBselect\fP() と全く同じ動作となる。 .SS シグナルとデータイベントを組み合わせる -ファイルディスクリプタが I/O 可能な状態になるのと同時に シグナルも待ちたい場合には、 \fBpselect\fP() が便利である。 -シグナルを受信するプログラムは、通常は、 シグナルハンドラをグローバルなフラグを立てるためだけに使う。 このグローバルなフラグは、 +ファイルディスクリプターが I/O 可能な状態になるのと同時に シグナルも待ちたい場合には、 \fBpselect\fP() が便利である。 +シグナルを受信するプログラムは、通常は、 シグナルハンドラーをグローバルなフラグを立てるためだけに使う。 このグローバルなフラグは、 そのイベントをプログラムのメインループで 処理しなければならないことを示す。 シグナルを受けると \fBselect\fP() (や \fBpselect\fP()) は \fIerrno\fP に \fBEINTR\fP をセットして戻ることになる。 シグナルがプログラムのメインループで処理されるためにはこの動作が不可欠で、 これがないと \fBselect\fP() は永遠に停止し続けることになる。 さて、メインループのどこかにこのグローバルフラグをチェックする 条件文があるとしよう。ここで少し考えてみないといけない。 「シグナルが条件文の後、しかし \fBselect\fP() コールの前に到着したら どうなるのか?」 答えは「その \fBselect\fP() は、たとえ解決待ちのイベントがあったとしても、 永遠に停止する」である。 この競合状態は \fBpselect\fP() コールによって解決できる。 -このコールを使うと、 \fBpselect\fP() で受信したいシグナルの集合だけをシグナルマスクに設定することができる。 +このコールを使うと、 \fBpselect\fP() でのみ受信したいシグナルの集合をシグナルマスクに設定することができる。 例えば、問題となっているイベントが子プロセスの終了の場合を考えよう。 メインループが始まる前に、 \fBSIGCHLD\fP を \fBsigprocmask\fP(2) でブロックする。 \fBpselect\fP() コールでは \fBSIGCHLD\fP を、もともとのシグナルマスクを使って有効にするのだ。 このプログラムは次のようになる。 @@ -219,15 +219,15 @@ main(int argc, char *argv[]) } .fi .SS 実例 -実際のところ \fBselect\fP() の大事な点は何なのか? ディスクリプタは好きなときに読み書きできるんじゃないの? \fBselect\fP() -の重要なところは、複数のディスクリプタを同時に監視でき、 なんの動きもなければプロセスを適切にスリープ状態に移行するところにあるのだ。 UNIX -プログラマは、 複数のファイルディスクリプタの入出力を同時に扱わねばならず、 しかもデータの流れは間欠的である、という状況によく出会う。 単に +実際のところ \fBselect\fP() の大事な点は何なのか? ディスクリプターは好きなときに読み書きできるんじゃないの? \fBselect\fP() +の重要なところは、複数のディスクリプターを同時に監視でき、 なんの動きもなければプロセスを適切にスリープ状態に移行するところにあるのだ。 UNIX +プログラマは、 複数のファイルディスクリプターの入出力を同時に扱わねばならず、 しかもデータの流れは間欠的である、という状況によく出会う。 単に \fBread\fP(2) や \fBwrite\fP(2) コールのシーケンスを作るだけでは、それらのコールのどれかが -ファイルディスクリプタからのデータを待ってブロックしており、 別のファイルディスクリプタには I/O が可能なのに使えない、 +ファイルディスクリプターからのデータを待ってブロックしており、 別のファイルディスクリプターには I/O が可能なのに使えない、 ということになってしまうだろう。 \fBselect\fP() を使うとこの状況に効果的に対処できる。 .SS "SELECT の掟" \fBselect\fP() を使おうとした多くの人は、理解しにくい挙動に出くわし、結果的に -できたものは移植性がないか、よくてもギリギリのものになってしまう。 例えば、上記のプログラムは、 集合に含まれるファイルディスクリプタを非停止 +できたものは移植性がないか、よくてもギリギリのものになってしまう。 例えば、上記のプログラムは、 集合に含まれるファイルディスクリプターを非停止 (nonblocking) モード にしなくても、どこにもブロックが生じないよう注意して書かれている。 微妙な間違いによって、 \fBselect\fP() を使う利点は簡単に失われてしまう。 そこで、 \fBselect\fP() コールを使うときに注意すべき重要事項を列挙しておくことにする。 .TP 4 @@ -239,11 +239,11 @@ main(int argc, char *argv[]) 上述したように、 効率的なプログラムを書くには \fInfds\fP の値を適切に計算して与えなければならない。 .TP 3. -\fBselect\fP() コールの終了後に結果をチェックして、 適切に対応するつもりのないファイルディスクリプタは、 どの集合にも加えてはならない。 +\fBselect\fP() コールの終了後に結果をチェックして、 適切に対応するつもりのないファイルディスクリプターは、 どの集合にも加えてはならない。 次のルールも参照。 .TP 4. -\fBselect\fP() から返った後には、全ての集合の全てのファイルディスクリプタについて 読み書き可能な状態になっているかをチェックすべきである。 +\fBselect\fP() から返った後には、全ての集合の全てのファイルディスクリプターについて 読み書き可能な状態になっているかをチェックすべきである。 .TP 5. \fBread\fP(2), \fBrecv\fP(2), \fBwrite\fP(2), \fBsend\fP(2) @@ -253,7 +253,7 @@ main(int argc, char *argv[]) .TP 6. 処理するデータ量が小さいことがはっきりとわかっている場合を除いて、 一度に 1 バイトずつ読み書きするようなことはしてはならない。 -バッファの許すかぎりのデータをまとめて読み書きしないと、 非常に効率が悪い。下記の例ではバッファは 1024 バイトにしているが、 +バッファーの許すかぎりのデータをまとめて読み書きしないと、 非常に効率が悪い。下記の例ではバッファーは 1024 バイトにしているが、 このサイズを大きくするのは簡単だろう。 .TP 7. @@ -265,13 +265,13 @@ main(int argc, char *argv[]) が返されることはないだろう。 .TP 8. -決して、引き数に長さ 0 のバッファを指定して \fBread\fP(2), \fBrecv\fP(2), \fBwrite\fP(2), \fBsend\fP(2) +決して、引き数に長さ 0 のバッファーを指定して \fBread\fP(2), \fBrecv\fP(2), \fBwrite\fP(2), \fBsend\fP(2) を呼び出してはならない。 .TP 9. \fBread\fP(2), \fBrecv\fP(2), \fBwrite\fP(2), \fBsend\fP(2) が \fB7.\fP に示した以外のエラーで失敗した場合や、 -入力系の関数の一つがファイル末尾を表す 0 を返した場合は、 そのディスクリプタをもう一度 select に渡しては\fIならない\fP。 -下記の例では、そのディスクリプタをただちにクローズし、 そこには \-1 をセットして、 それが集合に含まれ続けるのを許さないようにしている。 +入力系の関数の一つがファイル末尾を表す 0 を返した場合は、 そのディスクリプターをもう一度 select に渡しては\fIならない\fP。 +下記の例では、そのディスクリプターをただちにクローズし、 そこには \-1 をセットして、 それが集合に含まれ続けるのを許さないようにしている。 .TP 10. タイムアウトの値は \fBselect\fP() を呼ぶたびに初期化すべきである。 OS によっては timeout @@ -290,10 +290,10 @@ main(int argc, char *argv[]) .\" Having no file descriptors set is a useful .\" way to sleep the process with subsecond precision by using the timeout. .\" (See further on.) -\fBselect\fP() はファイルディスクリプタ集合を変更するので、 \fBselect\fP() -がループの中で使用されている場合には、呼び出しを行う前に毎回 ディスクリプタ集合を初期化し直さなければならない。 +\fBselect\fP() はファイルディスクリプター集合を変更するので、 \fBselect\fP() +がループの中で使用されている場合には、呼び出しを行う前に毎回 ディスクリプター集合を初期化し直さなければならない。 .SS "usleep エミュレーション" -\fBusleep\fP(3) 関数を持たないシステムでは、 有限のタイムアウトを指定し、ファイルディスクリプタを全くセットせずに \fBselect\fP() +\fBusleep\fP(3) 関数を持たないシステムでは、 有限のタイムアウトを指定し、ファイルディスクリプターを全くセットせずに \fBselect\fP() を呼び出すことで、これを代用できる。 以下のようにする。 .PP .nf @@ -305,9 +305,9 @@ main(int argc, char *argv[]) .PP 但し、これが動くと保証されているのは UNIX システムに限られる。 .SH 返り値 -成功すると、 \fBselect\fP() はファイルディスクリプタ集合に残っている ファイルディスクリプタの総数を返す。 +成功すると、 \fBselect\fP() はファイルディスクリプター集合に残っている ファイルディスクリプターの総数を返す。 -\fBselect\fP() がタイムアウトすると、返り値は 0 になる。 その時、ファイルディスクリプタ集合はすべて空である +\fBselect\fP() がタイムアウトすると、返り値は 0 になる。 その時、ファイルディスクリプター集合はすべて空である (しかしそうならないシステムもある)。 返り値が \-1 の場合はエラーを意味し、 \fIerrno\fP が適切にセットされる。エラーが起こった場合、 返された集合の内容や構造体 \fIstruct @@ -315,14 +315,14 @@ timeout\fP の内容は 未定義となっており、使用すべきではな を変更しない。 .SH 注意 一般的に言って、ソケットをサポートする全てのオペレーティングシステムは \fBselect\fP() もサポートしている。 \fBselect\fP() -を使うと、プログラマがスレッド、フォーク、IPC、シグナル、メモリ共有、 等々を使ってもっと複雑な方法で解決しようとする多くの問題が、 +を使うと、プログラマがスレッド、フォーク、IPC、シグナル、メモリー共有、 等々を使ってもっと複雑な方法で解決しようとする多くの問題が、 移植性がありかつ効率的な方法で解決できる。 .PP -\fBpoll\fP(2) システムコールは \fBselect\fP() と同じ機能を持っており、 まばらなファイルディスクリプタ集合を監視する場合に +\fBpoll\fP(2) システムコールは \fBselect\fP() と同じ機能を持っており、 まばらなファイルディスクリプター集合を監視する場合に いくらか効率がよい。 現在では広く利用可能であるが、以前は \fBselect\fP() より移植性の面で劣っていた。 .PP -Linux 独自の \fBepoll\fP(7) API は、多数のファイルディスクリプタを監視する場合に \fBselect\fP(2) や -\fBpoll\fP(2) よりも効率的なインタフェースを提供している。 +Linux 独自の \fBepoll\fP(7) API は、多数のファイルディスクリプターを監視する場合に \fBselect\fP(2) や +\fBpoll\fP(2) よりも効率的なインターフェースを提供している。 .SH 例 \fBselect\fP() の本当に便利な点を示す、よい例を紹介する。 以下のリストは、ある TCP ポートから別のポートへ転送を行う TCP フォワードプログラムである。 @@ -600,7 +600,7 @@ main(int argc, char *argv[]) あるいは、 \fBfcntl\fP(2) を使って非ブロック I/O をセットすれば良い、というアイデアもあるだろう。 これにも実際には問題があり、タイムアウトが非効率的に起こってしまう。 -このプログラムは一度にひとつ以上の同時接続を扱うことはできないが、 その様に拡張するのは簡単で、バッファのリンクリストを (接続ごとにひとつずつ) +このプログラムは一度にひとつ以上の同時接続を扱うことはできないが、 その様に拡張するのは簡単で、バッファーのリンクリストを (接続ごとにひとつずつ) 使えばよい。 現時点のものでは、新しい接続がくると古い接続は落ちてしまう。 .SH 関連項目 .\" .SH AUTHORS @@ -610,6 +610,6 @@ main(int argc, char *argv[]) \fBsigaddset\fP(3), \fBsigdelset\fP(3), \fBsigemptyset\fP(3), \fBsigfillset\fP(3), \fBsigismember\fP(3), \fBepoll\fP(7) .SH この文書について -この man ページは Linux \fIman\-pages\fP プロジェクトのリリース 3.68 の一部 +この man ページは Linux \fIman\-pages\fP プロジェクトのリリース 3.79 の一部 である。プロジェクトの説明とバグ報告に関する情報は http://www.kernel.org/doc/man\-pages/ に書かれている。