Unix-system-calls-pselect

提供:Dev Guides
移動先:案内検索

[top]#

[[File:]]

[[File:]]

|Web |This Site

  • 初心者向けのUnix *
  • 高度なUnix *

選択した読書

Copyright©2014 by finddevguides

  Home     References     Discussion Forums     About TP  

select()-Unix、Linuxシステムコール

[[File:]] image :http://www.finddevguides.com/images/next.gif [next] image:http://www.finddevguides.com/add- this.gif [AddThisソーシャルブックマークボタン]

広告

NAME

select、pselect、FD_CLR、FD_ISSET、FD_SET、FD_ZERO-同期I/O多重化

概要

/*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* ()および *pselect* ()を使用すると、プログラムは複数のファイル記述子を監視し、1つまたは複数のファイル記述子がI/O操作のクラス(入力可能など)の「準備完了」になるまで待機できます。 ブロックせずに対応するI/O操作(たとえば、 *read* (2))を実行できる場合、ファイル記述子は準備完了と見なされます。
*select* ()と *pselect* ()の操作は同じですが、3つの違いがあります。

Tag

説明

(i)

*select* ()は_struct timeval_(秒とマイクロ秒)であるタイムアウトを使用し、 *pselect* ()は_struct timespec_(秒とナノ秒)を使用します。

(ii)

*select* ()は、_timeout_引数を更新して、残り時間を示す場合があります。 *pselect* ()はこの引数を変更しません。

(iii)

*select* ()には_sigmask_引数がなく、NULL _sigmask_で呼び出された *pselect* ()として動作します。

ファイル記述子の3つの独立したセットが監視されます。 readfds_にリストされているものは、文字が読み取り可能になったかどうかを確認します(より正確には、読み取りがブロックされないかどうかを確認します;特に、ファイル記述子もファイルの終わりで準備ができています)、 writefds_内のものは書き込みがブロックされないかどうかを確認するために監視され、_exceptfds_内の例外は監視されます。 終了時に、セットはその場で変更され、どのファイル記述子が実際にステータスを変更したかを示します。 対応するクラスのイベントについてファイル記述子を監視しない場合、3つのファイル記述子セットのそれぞれをNULLとして指定できます。

セットを操作するための4つのマクロが提供されています。 FD_ZERO ()はセットをクリアします。 FD_SET ()および FD_CLR ()はそれぞれ、指定されたファイル記述子をセットに追加および削除します。 FD_ISSET ()は、ファイル記述子がセットの一部であるかどうかをテストします。これは、 select ()が戻った後に便利です。

_nfds_は、3つのセットのいずれかで最も大きい番号のファイル記述子に1を加えたものです。

_timeout_は、 select ()が戻るまでの経過時間の上限です。 ゼロになる可能性があり、 select ()がすぐに戻ります。 (これはポーリングに役立ちます。)_timeout_がNULL(タイムアウトなし)の場合、 select ()は無期限にブロックできます。

_sigmask_はシグナルマスクへのポインターです( sigprocmask (2)を参照)。 NULLでない場合、 pselect ()はまず現在のシグナルマスクを_sigmask_が指すものに置き換え、次に「選択」機能を実行してから、元のシグナルマスクを復元します。

_timeout_引数の精度の違いを除いて、次の pselect ()呼び出し:

ready = pselect(nfds, &readfds, &writefds, &exceptfds, timeout, &sigmask);

以下の呼び出しを実行する_atomically_と同等です:

sigset_t origmask; sigprocmask(SIG_SETMASK, &sigmask, &origmask); ready = select(nfds, &readfds, &writefds, &exceptfds, timeout); sigprocmask(SIG_SETMASK, &origmask, NULL);
*pselect* ()が必要な理由は、シグナルまたはファイル記述子の準備が整うまで待機する場合、競合状態を防ぐためのアトミックテストが必要だからです。 (シグナルハンドラーがグローバルフラグを設定して戻るとします。 そして、このグローバルフラグのテストとそれに続く *select* ()の呼び出しは、テストの直後で呼び出しの直前に信号が到着した場合、無期限にハングする可能性があります。 対照的に、 *pselect* ()を使用すると、最初に信号をブロックし、入ってくる信号を処理してから、必要な_sigmask_を指定して *pselect* ()を呼び出し、競合を回避できます。)

タイムアウト

関係する時間構造は_ <sys/time.h> _で定義され、次のようになります

struct timeval { long tv_sec; /*seconds*/ long tv_usec; /*microseconds*/ };

and

struct timespec { long tv_sec; /*seconds*/ long tv_nsec; /*nanoseconds*/ };

(ただし、POSIX.1-2001バージョンについては以下を参照してください。)

一部のコードでは、3つすべてのセットが空、_n_ゼロ、およびNULL以外の_timeout_を使用して select ()を呼び出し、サブ秒精度でスリープするかなり移植性の高い方法として使用します。

Linuxでは、 select ()は_timeout_を変更して、スリープしていない時間を反映します。他のほとんどの実装はこれを行いません。 (POSIX.1-2001はどちらかの動作を許可します。)これは、_timeout_を読み取るLinuxコードが他のオペレーティングシステムに移植されるときと、複数の select ()でstruct timevalを再利用するコードがLinuxに移植されるときに問題を引き起こします再初期化せずにループします。 select ()が戻った後、_timeout_が未定義であると考えてください。

返り値

成功した場合、 select ()および pselect ()は、返される3つの記述子セットに含まれるファイル記述子の数(つまり、readfds _、 writefds exceptfds_に設定されているビットの総数)を返します。興味深いことが起こる前にタイムアウトが切れた場合。 エラーの場合、-1が返され、_errno_が適切に設定されます。セットと_timeout_は未定義になるため、エラー後にそれらの内容に依存しないでください。

エラー

Tag Description
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 is negative or the value contained within timeout is invalid.
ENOMEM unable to allocate memory for internal tables.

#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) 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"); return 0; }

準拠

*select* ()はPOSIX.1-2001および4.4BSDに準拠しています( *select* ()は4.2BSDで初めて登場しました)。 一般に、BSDソケットレイヤーのクローンをサポートする非BSDシステム(System Vバリアントを含む)との間で移植可能です。 ただし、System Vバリアントは通常、終了前にタイムアウト変数を設定しますが、BSDバリアントは設定しないことに注意してください。
*pselect* ()はPOSIX.1gおよびPOSIX.1-2001で定義されています。

ノート

_fd_set_は固定サイズのバッファーです。 負の値またはFD_SETSIZE以上の_fd_の値で FD_CLR ()または FD_SET ()を実行すると、未定義の動作が発生します。 さらに、POSIXでは_fd_が有効なファイル記述子である必要があります。

関係するタイプに関して、古典的な状況は、timeval_構造の2つのフィールドが(上記のように)長く、構造が <sys/time.h> _で定義されていることです。 POSIX.1-2001の状況は

struct timeval { time_t tv_sec; /*seconds*/ suseconds_t tv_usec; /*microseconds*/ };

ここで、構造は_ <sys/select.h> で定義され、データ型_time_t_および_suseconds_t_は <sys/types.h> _で定義されます。

プロトタイプに関して、古典的な状況では、 select ()に_ <time.h> を含める必要があります。 POSIX.1-2001の状況では、 select ()および pselect ()に <sys/select.h> を含める必要があります。 Libc4とlibc5には <sys/select.h> _ヘッダーがありません。 glibc 2.0以降では、このヘッダーが存在します。 glibc 2.0では pselect ()の間違ったプロトタイプを無条件に提供し、glibc 2.1-2.2.1では _GNU_SOURCE が定義されている場合は pselect ()を提供し、glibc 2.2.2-2.2.4ではそれを提供します _XOPEN_SOURCE が定義されており、600以上の値があります。 間違いなく、POSIX.1-2001以降、デフォルトでプロトタイプを提供するはずです。

バージョン

*pselect* ()はカーネル2.6.16でLinuxに追加されました。 これに先立ち、 *pselect* ()はglibcでエミュレートされていました(しかしバグを参照)。

Linuxノート

Linux pselect ()システムコールは、_timeout_引数を変更します。 ただし、glibcラッパー関数は、システムコールに渡されるタイムアウト引数にローカル変数を使用することにより、この動作を隠します。 したがって、glibc pselect ()関数はタイムアウト引数を変更しません。これはPOSIX.1-2001で必要な動作です。

BUGS

Glibc 2.0は、_sigmask_引数を受け取らない pselect ()のバージョンを提供しました。

バージョン2.1以降、glibcは sigprocmask (2)および select ()を使用して実装される pselect ()のエミュレーションを提供しています。 この実装は、 pselect ()が防止するように設計された競合状態に対して脆弱です。 pselect ()が不足しているシステムでは、信頼性の高い(より移植性の高い)シグナルトラップをセルフパイプトリックを使用して実現できます(シグナルハンドラーは、もう一方の端が select ()メインプログラム。)

Linuxでは、 select ()はソケットファイル記述子を「ready for reading」として報告しますが、それでも後続の読み取りブロックはブロックします。 これは、例えば、データが到着したが検査時に誤ったチェックサムがあり廃棄された場合に起こり得る。 ファイルディスクリプタが誤って準備完了として報告されている他の状況があるかもしれません。 したがって、ブロックしてはいけないソケットにO_NONBLOCKを使用する方が安全かもしれません。

関連項目

*select_tut* (2)。

あいまいに関連するものについては、 accept (2)、 connect (2)、 poll (2)、 read (2)、 recv (2)、 send (2)、* sigprocmaskを参照してください*(2)、 write (2)、 epoll (7)、 feature_test_macros (7)

[[File:]] image :http://www.finddevguides.com/images/next.gif [next] [[File:]]

広告

  
Advertisements