select
複数のスレッドから同じ開いているファイル記述子を呼び出すとどうなりますか?
これはどこかに文書化されていますか?
POSIX 2008select
仕様によると、2 つのスレッドが同時に呼び出すことを禁止するものは何もありませんselect
。
両方のスレッドが重複するファイル記述子のセットを監視しており、共通ファイル記述子の一部が読み取り可能または書き込み可能になるか、エラーが診断された場合、両方のスレッドが共通ファイル記述子の準備ができているというレポートを返す可能性があると推測するのは合理的です。これは保証できません。心配するタイミングの問題があり、スレッドのスケジューリングなどに依存する可能性があります。また、スレッドの1つが、読み取るデータが含まれていると伝えられたファイル記述子で読み取るデータを見つけられない可能性があることも意味します。他のスレッドが最初にそこに到達しました。データの特定のバイトは、スレッドの 1 つだけによって読み取られます。
Linux のマニュアル ページによると、select
はスレッド セーフ機能であり、キャンセル ポイントです。
Linuxの一部のオペレーティング システムでは、1 つのスレッドが正常に に入り、select
他のスレッドはブロックされます (の本体select
はクリティカル セクションです)。最初のスレッドにどのような記述子が返されても、正常に入る 2 番目のスレッドは、レベル トリガー インターフェイスであるselect
ため、おそらく同じセットですぐにウェイクアップします。select
したがって、これらのオペレーティング システムのLinux ではselect
、ファイル記述子の複数のセットを同時に選択するために使用することはできません。
Linux は完全に再入可能な実行をサポートしているようで、このテスト プログラムで実証されています。
void * reader (void *arg) {
int *fds = (int *)arg;
struct timeval to = { 2, 0 };
fd_set rfds;
FD_ZERO(&rfds);
FD_SET(fds[0], &rfds);
select(fds[0]+1, &rfds, 0, 0, &to);
}
int main () {
int sp[2];
pthread_t t[2];
socketpair(AF_UNIX, SOCK_STREAM, 0, sp);
pthread_create(&t[0], 0, reader, sp);
pthread_create(&t[1], 0, reader, sp);
pthread_join(t[0], 0);
pthread_join(t[1], 0);
return 0;
}
このプログラムを Linux (私の場合は 2.6.43) で計測すると、プログラムは 2 秒後に戻り、両方のスレッドがselect
同時に開始されたことを示しています。