2012年3月19日月曜日

Man Page Of SELECT

Man page of SELECT Section: Linux Programmer's Manual (2)
Updated: 2010-08-31
Index JM Home Page roff page
 

名前

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 を足したものである。

timeoutselect() が復帰するまでの経過時間の上限である。 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) して、入ってくるシグナルを操作し、 望みの sigmaskpselect() を呼び出すことで、前記の競合を避けることができる。)  

タイムアウト

これらの関数で使用される時間関連の構造体は、 で以下のように定義されている。
 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 に追加された。 それ以前は、 pselect() は 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_tsuseconds_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() を使ってエミュレートされていた。 この実装にはきわどい競合条件において脆弱性が残っていた。 この競合条件における問題を防止するために pselect() は設計されたのである。 最近のバージョンの glibc では、カーネルがサポートしている場合には、 (競合が起こらない) pselect() システムコールが使用される。

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)



 

Index

名前
書式
説明
タイムアウト
返り値
エラー
バージョン
準拠
注意
Linux での注意
バグ
関連項目

This document was created by man2html, using the manual pages.

These are our most popular posts:

@IT:監視を自動化するSNMP(3)

2003年4月25日 ... SNMPの動作自体は名前の示すように非常にシンプルですが、アクセス対象であるMIB はお世辞にもシンプルとは言えません(第2 ... そこで、今回はこのMIBがどのような構造 をしているか、また標準MIBの中でも基本であるMIB-2にどのような情報が定義されて いるかを具体的に解説したいと思います。 ... どのような情報がMIBで管理されているか は機器によって異なりますが、SNMPで管理される機器は必ずMIBを保持しています。 .... icmpInParmProbs, Parameter Problem(パラメータ異常)の受信数 ... read more

例外処理(C# によるプログラミング入門)

堅牢なプログラムを作成するためには、 例外が起こったときでもプログラムが異常な 動作をしないよう、 しっかりと例外処理(exception ... このような例外が起きたとき、 例外処理用の構文が用意されていない言語ではどのように対処していたかというと、 「 通常は ... まず、関数定義側、すなわち、例外が発生する可能性のある側では、 throw 文を使って例外が起こったことを利用側に知らせます。 throw 文は以下のようにして 使用します。 read more

ハイパーテキスト転送プロトコル -- /1.1

1 導入: 1.1 目的: 1.2 必要条件: 1.3 専門用語: 1.4 全体の動作; 2 表記の慣習と一般 文法: 2.1 拡張 BNF: 2.2 基本的な規定; 3 プロトコルパラメータ: 3.1 の .... リソース {resource}: section 3.2 にて定義されるような、URI によって判別される ネットワークデータオブジェクト、あるいはサービス。 ... どのようなクライアントもサーバも キャッシュを持つ事は出来るが、トンネルとして振る舞っているサーバはキャッシュを使用 できない。 read more

Java - Wikipedia

Javaは例外処理機構を備えており、プログラム実行中に生じた異常(例外)の扱いを、 比較的安全な方法で行い、プログラムを読み ... Javaではガベージコレクションの機能が あるため、このようなことは無く、プログラマの負担は大きく軽減される。 ... これは、 ClassName a = new ClassName();ClassName b;b = aとすること により、bはaのフィールドを操作できる。 ...... ないため、開発者にはあまり理解されてい ない; プロジェクトでどのような再利用可能なオブジェクトが使えるようになっているか について、多く ... read more

Related Posts



0 コメント:

コメントを投稿