壊れたメガネ

ホッチキスの達人の意識の高いブログ。

termios.c_cc の VMIN VTIME について(メモ)

VMIN VTIME についてメモとしてここに自分なりにまとめてみます。
Gorilla という、シリアル通信のための PHP ライブラリを使うと色々捗ると思うので、ぜひ使ってください。

2012-11-18 追記

再び、ここに記してある4通りの方法試し、いくつか加筆修正しました。
誤っていた記述はあえて消さずに打ち消し線を用いています。

VTIME と VMIN

termios.c_cc[VMIN] と termios.c_cc[VTIME] (以下それぞれ VMIN VTIME) はデータ(character)読み込み時に、タイムアウトを規定するのに用いられる。ただしこのタイムアウトの設定はカノニカルモード、もしくは open(2) の際に O_NDELAY フラグを立てた場合に無視される。

VMIN は最低限読み込むデータサイズ(バイト数)を指す。この値に 0 が指定された場合に、 VTIME の指定する値が1バイトごとのタイムアウトまでの待ち時間となる。VTIME はデータを待ち受ける時間を 1/10 秒単位で指定する。

VTIME と VMIN の組み合わせと読み込みの挙動

VTIME を計るタイマーの挙動とブロックの振る舞いが VTIME と VMIN の組み合わせによって異なる。 以下に組み合わせとそれぞれの振る舞いを示す。

  • VMIN = 0 かつ VTIME = 0
    読み込み可能なデータがあればそれを読み込み、なければ何も読み込まずに呼び出し元に戻る。どちらの場合もブロックはされない。
  • VMIN > 0 かつ VTIME = 0
    データを最低 VMIN だけ受け取るまでブロックし続ける。 VMIN 以上のデータを受け取らないと呼び出し元に制御は戻らない。
  • VMIN > 0 かつ VTIME > 0
    データを VMIN だけ受け取るか、次のデータ読み込みまでに VTIME 以上費やした場合に呼び出し元に戻る。
    VTIME を計るタイマーは1バイト目のデータが来て初めて初期化される。いいかえるなら、1バイト目のデータがいつまでたっても来ないなら、無期限にブロックされ続ける。
    VMIN 未満のデータを受信した場合、1バイト目を受け取った時点でタイマーが初期化され、更にデータが送信されてくるのを待つ。この時 VTIME 内に受信データの合計サイズが VMIN かそれ以上になった時点で read(2) は受信データを返し、制御は呼び出し元に戻る。一方 VTIME 内に受信データの合計サイズが VMIN を満たさなかった場合、 read(2) は少なくともその時点までに受け取ったデータを返し、制御は呼び出し元に戻る。
  • VMIN = 0 かつ VTIME > 0
    1バイトでも読み込み可能なデータがあればそれを読み込み、呼び出し元に戻る。ただし VTIME で指定した時間内は、 read(2) で指定したサイズを読み込もうとし、この間ブロックする。
    読み込み可能なデータがない場合、データが送られてくのを VTIME だけ待ち、その間ブロックする。 VTIME を過ぎてデータがない場合、何も読み込まずに呼び出し元に戻る。
    VTIME 内に1バイト目を受け取り、続くデータがバッファに残っていても read(2) が残りすべてを読み込むとは限らない。

参考

Serial Programming Guide for POSIX Operating Systems
Understanding UNIX termios VMIN and VTIME