標準/拡張機能 | C/C++ | 依存項目 |
---|---|---|
XPG4.2 |
両方 |
#define _XOPEN_SOURCE_EXTENDED 1
#define _OPEN_MSGQ_EXT
#include <sys/types.h>
#include <sys/time.h>
#include <sys/msg.h>
int select(int nmsgsfds, fd_set *__restrict__ readlist,
fd_set *__restrict__ writelist, fd_set *__restrict__ exceptlist,
struct timeval *__restrict__ timeout);
#define _POSIX_C_SOURCE 200112L
#include <sys/select.h>
int pselect(int nmsgsfds, fd_set *__restrict__ readlist,
fd_set *__restrict__ writelist, fd_set *__restrict__ exceptlist,
const struct timespec *__restrict__ timeout,
const sigset *__restrict__ sigmask);
#define _OE_SOCKETS
#define _OPEN_MSGQ_EXT
#include <sys/types.h>
#include <sys/time.h>
#include <sys/msg.h>
int select(int nmsgsfds, fd_set *readlist,
fd_set *writelist, fd_set *exceptlist,
struct timeval *timeout);
メッセージ・キューを監視する場合 (X/Open ソケットのみ) は、_OPEN_MSGQ_EXT を定義する必要があります。
pselect() および select() 関数は、ソケットおよびメッセージ・キューのいずれかで、読み取り、書き込みが行われなかったかを調べ、あるいは保留中の例外処理条件を調べるために、タイムアウトが起こるまで、ソケットのセットのアクティビティーまたはメッセージ・キュー ID のセットのアクティビティー (あるいはその両方) をモニターします。またこの呼び出しは、通常のファイル記述子、パイプ、および端末を指定しても 機能します。
select() 関数は、以下の点を除いて pselect() 関数と同じです。
このパラメーターは、2 つの部分に分かれます。最初の半分 (高位 16 ビット) は、メッセージ・キュー ID を含む配列のエレメント数を 指定します。この数は、値 32767 を超えてはなりません。
後半 (下位 16 ビット) は、検査を行うファイルまたはソケット記述子に 対応するビット・セット内のビット数を指定します。この値は、+ 1 の検査を行う最大記述子数と等しくする必要があります。
どちらの部分の nmsgsfds パラメーターも値 0 と等しい場合には、対応するビット・セットまたは配列が存在していないと想定されます。
_OPEN_MSGQ_EXT が定義されていない場合は、ファイルまたはソケット記述子だけしか監視されないことがあります。この場合、nmsgsfds を FD_SETSIZE (sys/time.h で、2048 に 定義されている) より小さいか等しくて、ゼロより大きいか等しくする必要があります。 また、FD_SETSIZE はユーザーのプログラムで定義できません。
ファイルまたはソケット記述子を指定するのに使用されるビット・セットは、可能なすべてのファイルまたはソケットについて 1 ビットのサイズに固定されます。nmsgsfds パラメーターを使用して、pselect() または select() は、割り振られたビット・セットのサブセットだけを強制的に検査します。
アプリケーションでソケット 3、4、5、6、および 7 が割り振られ、すべての 割り振りを検査したい場合には、nmsgsfds の後半部分は指定 した最高位記述子 7 に 1 をプラスした 8 に設定する必要があります。アプリケーションでソケット 3、4 を検査する場合は、nmsgsfds の後半部分は 5 に設定する必要があります。
2048 から 65534 の間の記述子番号について選択するには、 _OPEN_MSGQ_EXT または _OPEN_SYS_HIGH_DESCRIPTORS フィーチャー・テスト・マクロが 定義されている必要があり、デフォルトのサイズより大きいビット・セットを使用しな ければなりません。 メッセージ・キューについても選択する場合 (_OPEN_MSGQ_EXT が定義されていると きに可能)、最大の記述子番号は 2047 に制限されます。 65535 から 524287 の間の記述子番号について選択するには、フィーチャー・テス ト・マクロ _OPEN_SYS_HIGH_DESCRIPTORS が定義されている必要があり、フィーチャー ・テスト・マクロ _OPEN_MSGQ_EXT は定義されていてはなりません。また、プロセスの MAXFILEPROC の限界は 65536 より大きいことが必要です。このフィーチャーがあれば、(メッセージ・キューなしで) いくつのソケットについ てでも選択できます。 この場合には、FD_SETSIZE も再定義できますが、アプリケーション で malloc() を使って、それより大きいビット・セットを割り振るようにお勧めします。
struct sellist {
fd_set fdset; /* file/socket descriptor bit set */
int msgids[max_size]; /* array of message queue identifiers */
};
sellist 構造体を使用している場合に、監視できる最高位記述子は 2047 です。
以下で、型 fd_set の説明をします。msgids 配列の各整数により、状況を検査するメッセージ・キュー ID が 指定されます。-1 の値のあるエレメントは受け入れ可能で、無視されることになります。前半部分の nmsgsfds に含まれる値によって、検査される配列の エレメント数が正確に判別されます。
timeout が NULL ポインターではない場合には、選択が完了するのを待機する最大インターバルが指定されます。最大タイムアウト値は、31 日です。timeout が NULL ポインターの場合には、ソケットまたはメッセージが 作動可能になるまで、pselect() および select() 呼び出しがブロックします。ソケットをポーリングし、即時に戻すためには、timeout がゼロ値 timeval 構造体または timespec 構造体の NULL 以外のポインターであることが必要です。
sigmask が NULL ポインターでない場合、pselect() 関数は記述子が試行される前の sigmask が指すシグナルのセットによる呼び出し元のシグナル・マスクを置き換え、戻る前に呼び出しスレッドのシグナル・マスクを保管します。
一度に複数のソケットをテストできるように、テストするソケットは、fd_set 型のビット・セット中に入れられます。ビット・セットは、x がセットのエレメントの場合に、x を表すビットは 1 に設定されるような、ビットのストリングです。x がセットのエレメントでない場合は、 x を表すビットは 0 に設定されます。例えば、ソケット 33 がビット・セットのエレメントである場合には、ビット 33 を 1 に設定します。ソケット 33 がビット・セットのエレメントでない場合には、ビット 33 を 0 に設定します。
アプリケーション・プログラムは、パラメーター readlist、writelist、および exceptlist が、パラメーター nmsgsfds の大きさのビット・ストリングを指していることを確認する必要があります。z/OSUNIX サービスは、ビット・ストリングのそれぞれについて、ビット 0 ~ n-1 (この場合、n は nmsgsfds の 2 番目のハーフワード) のアクセスを試みます。ビット・ストリングが短すぎると、アプリケーション・プログラムの実行時に、予測できない結果を受け取ることになります。
ソケットは、着信データがそのためにバッファーに入れられるか、あるいは 接続要求が保留中のときに、読み取りの作動が可能になります。ソケットのいずれかが読み取り作動可能になっているかどうかをテストす るには、関数が動的に割り振られていた場合は、FD_ZERO() または memset() を使って readlist の fdset ビット・セットを 初期化して、テストする各ソケットごとに FD_SET() を呼び出します。
発信データ用のバッファー・スペースがある場合には、ソケットは書き込み可能です。ソケット上に、受信されるデータがあれば、ソケットは読み取り作動可能です。 接続プロセス中の非ブロッキング・ストリーム・ソケットの場合、connect() は -1 で戻ります。プログラムは、errno を検査する必要があります。 errno が EINPROGRESS の場合、connect() の完了時にソケットは書き込みのために選択されます。errno が EINPROGRESS ではない状態では、ソケットはさらに書き込み用に選択されますが、それは、ソケット上に未解決のエラーがあることを示します。データ量がバッファー・スペース量より少ないと、 write()、send()、または sendto() への呼び出しはブロックしません。ソケットが書き込み用に選択されている場合は、使用可能なバッファー・ス ペース容量は、getsockopt() で SO_SNDBUF を 使用して戻されるサイズ以上になるよう保証されています。ソケットのいずれかが書き込み作動可能状態かどうかをテストするには、関数が動的に割り振られていた場合は FD_ZERO() または memset() を使って writelist 内の fdset ビット・セットを初期化して、テストする各ソケットに対して FD_SET() を使用します。
メッセージ・キューは、メッセージがあるときならいつでも読み取り可能です。これは、満杯でないときならいつでも、書き込み可能です。メッセージ・キューが満杯なのは、メッセージ限界数に達したか、あるいは バイト数制限に達したときです。例外条件は、select() 呼び出し元がメッセージ・キューで待機中に このキューが削除される時に存在します。
プログラマーは、readlist、writelist、および exceptlist パラメーターのいずれかの NULL を渡すことができます。ただし、これらが NULL ではないときには、すべて同じ型の構造体を示す 必要があります。例えば、readlist で sellist が示されるとします。 writelist が NULL ではないときには、これで sellist も示す必要が あります。writelist が、NULL ではないとします。プログラマーが、読み取り状況のみについてファイル記述子のセットを検査する 場合には、writelist により示される sellist 構造体のビット・セットの、該当するビットを 0 に設定する必要があります。プログラマーが書き込み状況のみについて、メッセージ・キューのセットを検査する 場合には、readlist により示される sellist 構造体の配列の該当エレメント を -1 に設定する必要があります。通常ファイルは常に、読み取りおよび書き込み作動可能の状態です。
pselect() および select() に渡されたソケットのセットがビット・セットのため、その状況のソケットをポーリングする前に、pselect() および select() 呼び出しで、各ビット・セットのそれぞれのビットをテストする必要があります。pselect() および select() 呼び出しでテストされるのは、範囲が 0 から n-1 (ここで は、n = nmsgsfds の 2 番目の ハーフワードの値) のソケットだけです。
C++ の特殊な動作: C++ でこの関数を使用するには、_XOPEN_SOURCE_EXTENDED 1 フィーチャー・テスト・マクロを 使用する必要があります。
値 -1 は、エラーについて調べる必要があるエラー・コードを示します。値ゼロは、時間制限が満了であることを示します。
戻り値が 0 より大きい場合には、高位 16 ビットで メッセージ・キューが指定され、下位 16 ビットで記述子数が指定されるので、この戻り値は nmsgsfds と類似しています。これらの値は、読み取り、書き込み、および例外のそれぞれの基準を満たす合計値を示します。記述子またはメッセージ・キューは、複数の指定基準を満たす場合には、複数回カウントされる場合があることに注意してください。メッセージ・キューの戻り値が値 32767 を超えていても、32767 だけが報告されることになります。これは、戻り値が負の値にならないようにするためです。ファイル/ソケット記述子の戻り値が 65535 を超えていても、65535 だけが報告されることになります。
#define _XOPEN_SOURCE_EXTENDED 1
#define _OPEN_MSGQ_EXT
#include <sys/types.h>
#include <sys/time.h>
#include <sys/msg.h>
struct sellist {
fd_set fdset;
int msgids[2];
};
/*
* sock_msg_stats(sr, sw, se, mr, mw, me) - Print the status of
* sockets sr, sw, and se, and of message queue ids mr, mw,
* and me.
*/
int sock_msg_stats(sr, sw, se, mr, mw, me)
int sr, sw, se, mr, mw, me;
{
struct sellist *reading, *writing, *excepting;
struct sellist read, write, except;
struct timeval timeout;
int rc, max_sock, sock_size, nmsgsfds;
int msgids[1]; /* we only check 1 message queue */
/* What's the maximum socket number? */
max_sock = MAX( sr, sw );
max_sock = MAX( max_sock, se );
/* initialize the static bit sets */
FD_ZERO( &read.fdset ); reading = &read;
FD_ZERO( &write.fdset ); writing = &write;
FD_ZERO( &except.fdset ); excepting = &except;
/* add sr, sw, and se to the appropriate bit set */
FD_SET( sr, &reading->fdset );
FD_SET( sw, &writing->fdset );
FD_SET( se, &excepting->fdset );
/* initialize the message id arrays */
reading->msgids[0] = mr;
writing->msgids[0] = mw;
excepting->msgids[0] = me;
/* set the nmsgsfds parameter */
_SET_FDS_MSGS( nmsgsfds, 1, max_sock+1 );
/* make select poll by sending a 0 timeval */
memset( &timeout, 0, sizeof(timeout) );
/* poll */
rc = select( nmsgsfds, reading, writing, excepting, &timeout);
if ( rc < 0 ) {
/* an error occurred during the SELECT() */
perror( "select" );
}
else if ( rc == 0 ) {
/* no sockets or messages were ready in our little poll */
printf( "nobody is home.¥n" );
} else
if (_NFDS(rc) > 0) {
/* at least one of the sockets is ready */
printf("sr is %s¥n",
FD_ISSET(sr,&reading->fdset) ? "READY" : "NOT READY");
printf("sw is %s¥n",
FD_ISSET(sw,&writing->fdset) ? "READY" : "NOT READY");
printf("se is %s¥n",
FD_ISSET(se,&excepting->fdset) ? "READY": "NOT READY");
} else
if (_NMSGS(rc) > 0) {
/* at least one message queue is ready */
printf("mr is %s¥n",
reading->msgids[0] == -1 ? "NOT READY" : "READY");
printf("mw is %s¥n",
writing->msgids[0] == -1 ? "NOT READY" : "READY");
printf("me is %s¥n",
excepting->msgids[0] == -1 ? "NOT READY" : "READY");
}
}
CELEBP72
⁄* CELEBP72
This example demonstrates the use of pselect()
Expected output:
Parent: Issuing pselect
This is the child
Child: Sending signal to the parent at:
This is the signal handler
Signal received: 14 (14 is SIGALRM)
The pselect call was made at:
The SIGALRM was caught at:
TEST PASSED!
*⁄
#define _POSIX_C_SOURCE 200112L
#include <sys⁄select.h>
#include <stdio.h>
#include <fcntl.h>
#include <signal.h>
#include <string.h>
#include <time.h>
#include <unistd.h>
time_t t1,t2;
void incatchr(int signum){
double diff=0;
time(&t2);
printf("¥n¥nThis is the signal handler¥n");
printf("Signal received: %d (14 is SIGALRM) ¥n",signum);
printf("The pselect call was made at: ¥t%s¥n",ctime(&t1));
printf("The SIGALRM was caught at: ¥t%s¥n",ctime(&t2));
diff = difftime(t2,t1);
if(diff < 10) {
printf("TEST FAILED!¥n¥n");
}
else{
printf("TEST PASSED!¥n¥n");
}
}
int main(void){
int fd[1], rc, nfds=3, fd1, fd2, fd3;
pid_t cpid, ppid;
fd_set fdsread;
struct sigaction action, info;
sigset_t pselect_set;
struct timespec t;
time_t t3;
t.tv_sec=10;
t.tv_nsec=0;
FD_ZERO(&fdsread);
action.sa_handler = incatchr;
action.sa_flags = 0;
sigaction(SIGALRM,&action,&info);
sigemptyset(&pselect_set);
sigaddset(&pselect_set, SIGALRM);
fd1 = open(".⁄testchd.txt",O_RDWR|O_CREAT);
fd2 = open(".⁄testchd2.txt",O_RDWR|O_CREAT);
if((rc=pipe(fd)) != 0){
printf("Error in pipe¥n");
return(-1);
}
FD_SET(fd[0],&fdsread);
if ((cpid = fork()) < 0){
printf("Fork error¥n");
return(-1);
}
else{
if (cpid == 0){
fd3 = open(".⁄testchd.txt",O_RDWR|O_CREAT);
printf("This is the child¥n");
sleep(2);
ppid= getppid();
time(&t3);
printf("Child: Sending signal to the parent at: ");
printf("%s",ctime(&t3));
kill(ppid,SIGALRM);
sleep(3);
_exit(0);
}
else{
printf("Parent: Issuing pselect¥n¥n");
time(&t1);
if (pselect(nfds,&fdsread,NULL,NULL,&t,&pselect_set) == -1)
printf("Error in pselect¥n");
}
close(fd[0]);
}
return 0;
}