1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

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

Last updated at Posted at 2020-06-18

#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でブロッキングできる代償は未定義動作だ。

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

1
1
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?