さいきんブログを書いていないと思ったら今年に入ってから更新をしていなかった。
覚えている部分からとりあえず気がついたことをメモしておこうと思う。
今回は pipe と fd のフラグについて。
Linux ほか *nix のシステムでは
このパイプの fd には
つまり,パイプはノンブロッキングに読める。
手元の ArchLinux で Linux 4.12,glibc 2.25 を使ってるとデフォルトでこのフラグが立ってたっぽくて予想してない挙動に気がつかなくてハマった。
フラグの確認方法は,
逆にフラグをセットするならば,
フラグの消去もまた同様。
この場合,fd を
なので,
この場合,
ただ,この例のように continue するだけならそもそも読み出しでブロックさせとけば良いので,元よりフラグを消しておけば済む話である。
これに気がつかずにわりとハマりました。
覚えている部分からとりあえず気がついたことをメモしておこうと思う。
今回は pipe と fd のフラグについて。
Linux ほか *nix のシステムでは
pipe(2)
というシステムコールでプロセス間通信用の fd を作成できる。このパイプの fd には
O_NONBLOCK
というフラグを立てたり消したりすることが可能である。つまり,パイプはノンブロッキングに読める。
手元の ArchLinux で Linux 4.12,glibc 2.25 を使ってるとデフォルトでこのフラグが立ってたっぽくて予想してない挙動に気がつかなくてハマった。
フラグの確認方法は,
#inlude <fcntl.h>この返却値を調べれば良い。
...
fcntl( fd, F_GETFL );
逆にフラグをセットするならば,
#include <fcntl.h>のように取得したフラグに立てたいフラグを追加すれば良い。
...
fcntl( fd, F_SETFL, fcntl(fd, F_GETFL) | O_NONBLOCK );
フラグの消去もまた同様。
O_NONBLOCK
が立てられていた場合について。この場合,fd を
read(2)
で読むと,まだ何もデータが到着していない場合,read(2)
は -1 を返却する。なので,
while( read( fd, buf, sizeof(buf) ) > 0 ) {などという手抜きコードを書いていると
...
read(2)
はブロックしないので何も読まずに終わることがある。この場合,
for(;;) {という風に
ssize_t read_size = read( fd, buf, sizeof(buf) );
if ( read_size < 0 ) {
if ( errno == EAGAIN ) { continue; }
else { break; }
} else {
...
read(2)
の返却値が正の値じゃない場合かつerrno
にEAGAIN
が入っていた場合もきちんとフォローしましょう。ただ,この例のように continue するだけならそもそも読み出しでブロックさせとけば良いので,元よりフラグを消しておけば済む話である。
これに気がつかずにわりとハマりました。