fifo
FIFOは名前付きパイプらしい.パイプがファイルで嬉しくなる.
man 4 fifoによると,FIFOとは先入先出特殊ファイル,名前付きパイプで,パイプとことなる点は,ファイルシステムに関連付けられていることである.popen関数やpipe関数でファイルストリームやファイルディスクリプタを取得できたことから考えて,この機構があるのは予想通りで期待通りだろうか.FIFOはコマンドラインでも堪能(?)できる.
mkfifo hoge cat < hoge & echo "hogefugafoo"などとする.このときls -lとすると
prw-r--r-- 1 foo foo 0 4月 13 01:53 hogeと最初の文字がパイプのpになっている.以下,FIFOについてまとめてみた(man 4 fifoをまとめただけ).
- いくつかのプロセスによってオープンされている一つのFIFOについて一つのパイプが管理される.
- FIFOにデータが渡されるときは,読み出しと書き込みの両方(パイプの両端)がオープンされている必要がある.
- 通常はFIFOをオープンすると,もう一端がオープンされるまでブロックされる.
- ノンブロッキングモードでFIFOをオープンしたときの動作は以下のようになる.
- 書き込み側がオープンされていない状態で読み込み専用でオープンした場合.
- 成功.
- 読み込み側がオープンされていない状態で書き込み専用でオープンした場合.
- 失敗(ENXIO).さらにオープンしようとしたそのプロセスにSIGPIPEが送られる.
- 読み書き両用でオープンした場合,Linuxではブロッキングモード,ノンブロッキングモードともに成功する(これはPOSIXでは定義されていない).
先にコマンドラインからmkfifoでFIFOを作成した.他にも
mknod hoge pで作成することができる.CでのFIFOの作成する方法にも両者に対応する同名の関数mkfifoとmknodがある.mknodの方が移植性が高いらしいが,man mknodによるとFIFOはmkfifoで作成すべきとある.以下にmkfifoとmknodそれぞれでFIFOを作成するサンプルを示す.
FIFOを使用するサンプルを作ってみた.まずはFIFOから読み込むサンプルfifo-reader.
そしてFIFOに書き込むサンプルfifo-writer.
そして実行.
fifo-readerとしておいて,別のコンソールで
fifo-writerなどとする.ある時間内であれば,同時にfifo-writerを複数起動して一つのfifo-readerに読ませることができる.
for A in $(seq 1 10); do fifo-writer & done複数のfifo-writerを起動しても正確にfifo-readerが動作するための注意は,「一回でreadするサイズは,後者で一回でwriteするサイズにそろえる」ことである.サンプルではこれらは
#define BUF_SIZE PIPE_BUFで設定できるが,両者のBUF_SIZEの値が異なると,予期しない結果になったりする.例えば上記のサンプルのfifo-readerの出力は
make /tmp/fifo-sample 8198 received 4096 bytes: My pid = 8200. 8198 received 4096 bytes: My pid = 8204. 8198 received 4096 bytes: My pid = 8205. 8198 received 4096 bytes: My pid = 8206. 8198 received 4096 bytes: My pid = 8202. 8198 received 4096 bytes: My pid = 8203. 8198 received 4096 bytes: My pid = 8201. 8198 received 4096 bytes: My pid = 8209. 8198 received 4096 bytes: My pid = 8207. 8198 received 4096 bytes: My pid = 8208. 8198 received 0 bytes:となる.これはfifo-writerを
for A in $(seq 1 10); do ./fifo-writer & doneとした結果である.これをfifo-readerで
#define BUF_SIZE (PIPE_BUF*2)などとすると,fifo-readerの出力は
8237 received 8192 bytes: My pid = 8239. 8237 received 8192 bytes: My pid = 8243. 8237 received 8192 bytes: My pid = 8244. 8237 received 8192 bytes: My pid = 8246. 8237 received 8192 bytes: My pid = 8247. 8237 received 0 bytes:と期待しない結果になってしまう(10のfifo-writerでFIFOに書き込んだのに5個分しか出力がない).

