C言語

【C言語】select関数の使い方、間違っていませんか?

2021年12月31日

関数仕様

書式

引数

nfds 3つの集合(readfds,writefds,exceptfds)に含まれるファイル記述子の最大値に 1 を足したもの
readfds 読み出しが可能かどうかを監視するファイルディスクリプタの集合へのポインタ or NULL
writefds 書込みが可能かどうかを監視するファイルディスクリプタの集合へのポインタ or NULL
exceptfds 例外が発生したかどうかを監視するファイルディスクリプタの集合へのポインタ or NULL
timeout タイムアウトになる時間を指定する timeval 構造体へのポインタ (NULL の場合は無期限)
fds ファイルディスクリプタの集合へのポインタ
fd ファイルディスクリプタ

戻り値

正の値 変化があったファイルディスクリプタの総数(readfds,writefds,exceptfds)
0 タイムアウト
-1 エラーが発生(errno にエラー番号がセットされています)

代表的なエラー(errno)

  • EBADF
    何れかの集合(fds)に無効なファイルディスクリプタが設定されている
    例えば、既にクローズされているディスクリプタ、など
  • EINTR
    引数の timeout が示す時間経過前、または記述子に変化が発生する前に
    シグナルに割り込まれた
  • EINVAL
    引数の nfds が負の値、またはリソース上限 RLIMIT_NOFILE より大きい
  • ENOMEM
    カーネルの内部テーブルにメモリを割り当てることができなかった

 

機能

  • 複数のファイルディスクリプタを同時に監視します
    readaccept などのシステムコールを呼び出すと、データが到着したり接続要求が発生するまでシステムコールから戻ってきません。変化を同時に待ち受ける仕組みselect システムコールです
  • 引数 timeout にタイムアウトを設定できます
    timeout が示す時間内にファイルディスクリプタに変化が無かった場合、時間切れとして select からリターンします

 

集合を扱うためのマクロ

  • FD_ZERO
    集合(fds)を初期化する(セットされている全てのファイルディスクリプタを集合から削除)
  • FD_SET
    集合(fds)に、ファイルディスクリプタ(fd)をセットする
  • FD_CLR
    集合(fds)にセットされているファイルディスクリプタ(fd)を、集合から削除する
  • FD_ISSET
    集合(fds)にファイルディスクリプタがセットされているかを調べる
    ※このマクロは select() が終了した後に使うと便利

 

注意すること

注意ポイント

select() から復帰した後の timeout の値は信用してはいけない

Linux では、select がタイムアウト以外で戻った際、timeout に残りの時間を反映するようになっています。
しかし、他のほとんどの OS では、このようになっていません (POSIX.1-2001は両方の動作を認めています)。

そのため、timeout を参照している Linux のコードを他の OS へ移植する場合に問題が起きます。
select() から復帰した後、timeout は未定義であると考えておく方が無難でしょう。

 

サンプルプログラム

 

こちらの記事もよく読まれています

  • この記事を書いた人
  • 最新記事
SANACHAN

SANACHAN

「生涯一エンジニア」を掲げ、大手グローバル企業でSE/PGとして8年勤め、キャリアアップ転職した現役のエンジニアです。世にあるメジャーな全プログラム言語(コボル除く)を自由に扱えます。一児の父。自分のため、家族のため、日々勉強してます。システムエンジニア、プログラミングに関する情報を蓄積している雑記帳です。

-C言語
-, ,