Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
Help us understand the problem. What is going on with this article?

FIFOについてもう少し(追記

FIFOとは

パイプに名前をつけたものがFIFO。終わってしまった。
ls -l | grep keyword
における | がパイプで、これにファイルシステムグローバルな名前をつけたものがFIFOということになる。性質はパイプと変わらない。上記の例だと

1.grepが起動してパイプのopen(O_RDONLY)でブロッキング
2.lsがパイプをopen(O_WRONLY)で開き
3.lsが出力をパイプにwrite()
4.grepのブロックが解除され、入力をread()
5.lsがパイプをclose()
6.grepがパイプをclose()

みたいな動きになる。
open()でブロッキングするのであってread()やwrite()ではブロッキングしない。
O_RDONLYではopen()でブロック
O_RDWRではread()でブロック
という挙動になる。
こんなのどこに書いてあるんだ?

これは日本語man pagesに書いてあるのだがわかりづらい。つまりこうだ。

seekのきかないファイル(パイプやFIFO)は現在位置から読み込みを開始して、データがない場合はEOFとみなして0を返す。
EOFを返すのはO_RDONLYでのopenが成功した(有効なfdが返された)場合、かつFIFOにデータがない場合だけである。

ゆえにread()ではブロッキングしない。openモード次第でブロックの挙動が変わる。上記参照。通常はこれで困ることはないが、プロセス間通信でスレッドを立てて、ループでデータの到着を待つような処理をする場合、open()でブロッキングしてCPUの浪費を防ぐ必要がある。しかし人情として、いちいちループ中でopen()/close()はしたくない。read()でブロッキングが可能ならそれがベストだ。
些細な問題を除いてreadでもブロッキングはできるのだが、mqで解決したのでそれはまあ良しとしよう。

そこでメッセージキュー

POSIXメッセージキューは固定サイズのメッセージを有限個格納できるキューである。作成時にブロッキング属性を付与するため、キューの受信を実行しても(ブロッキングキューであれば)メッセージ到着までブロッキングしてくれる。
なのでスレッドのループ中でメッセージの到着を待つような処理に向いている。パイプのようにSIGPIPEを発生することもなければ、FIFOの両端が閉じるとデータを失うようなこともない(カーネル寿命なのでシャットダウンまでデータを保持してくれる)。

プロセス間のデータ交換

プロセス間通信の方法は、ほかにもセマフォやシグナル、共有メモリなどがあるそうなのだが、データ交換を目的に行う場合はFIFOかキューかドメインソケットになると思う。それぞれ一長一短はあると思うのでいずれまとめてみたい。

で、些細な問題って何?

googleでman fifoとかで検索するとヒットするのだが、

FIFOに対してO_RDWR指定でopenした場合の動作は未定義である。readでブロッキングできる代償は未定義動作だ。

まあ承知の上で使うならいいのではないだろうか。個人的にはこういう逃げ口上のようなマニュアルは大嫌いだが。

pff01632
だがそのクソコードは日本じゃあ二番目だ。
http://blog.livedoor.jp/craftdofus/
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away