0
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 5 years have passed since last update.

言葉が足りなかったな、すまん(追記

Last updated at Posted at 2020-06-12

前回の記事では割とわけのわからんことを書いたと反省。
まあやりたかったことはこうだ。Linux環境において、

1.プロセスAとプロセスBで少量のデータを一方通行に送りたい
2.割とタイムクリティカルな制約でやりたい
3.通信経路をread()でブロッキング監視したい

最後の3はCPUを無駄食いさせないためだ。そしてこの仕様を満たすために使おうとしたのがFIFO、名前つきパイプだった。

プロセス間通信のやり方はいろいろあるが、

・ドメインソケットは便利だがオーバーヘッドが気になる。
・共有メモリは高速だがCPUの無駄食い対策がしにくい。
・read()でブロッキングしてOSにディスパッチを任せたい。

ということでFIFOを使ってみた。結果、大外れであった。

まずfdのopen()が曲者で、FIFOに対する使用 の場合

write側だけをopen()するとSIGPIPEを発生する(無視もできる)
 ※SIGPIPEは改めて調べる
・ブロッキングopen()するとread()がブロッキングしない
 ※openモードで挙動が違う
・ノンブロッキングでopen()するとread()でブロッキングできない
・FIFOの両端が閉じるとその瞬間に抱えているデータが消える

とまあどこまでも扱いにくい代物であった。

やむを得ず
open()でブロッキングして
データが到着したらread()して
close()で最初に戻る

という実装をテストしてみたが、open()/close()の遅延がでかい。
最初のタイムクリティカルな制約を満たせなくなってしまった。

そうじゃない。やりたいことは違うんだ。

1.通信経路をブロッキング指定でopen()するが即時復帰して
2.通信経路をread()したらデータ到着までブロッキングして
3.あとは2をループ中で繰り返せばオーバーヘッドが最小
4.ループが終わったら通信経路をclose()

これを満たすAPIを探していたのだ。そしてついに見つけた。
POSIXメッセージキューがそれだった。
こいつはSystemVメッセージキューを拡張したものだ。

・一度キューを作ればプロセスが落ちてもカーネル寿命で存在する
・両端が閉じてもデータを失うことがない
・read端とwrite端のどちらを先にオープンしてもよい
・mq_open()しても即時復帰する
・mq_receive()を呼ぶとブロッキングモードならデータを待つ
・相手側プロセスがmq_send()すれば起床してデータが取れる
・しかも動作が思ったより高速である
・メッセージに優先度をつけたりシグナルを送ったりできる
 (使わないけど)

とまあ、いいことずくめのようだが少々のクセはある。
「メッセージ」の「キュー」なので、データはパケット扱いだ。
パイプのようなバイトストリームではない。
それと、キュー作成時のパラメータをいくつか指定するのだが

・ブロッキングかノンブロッキングか
・1メッセージのサイズ
・キューが保持可能なメッセージ数
・あとなんか1つ(忘れた)

を指定する必要がある。

・データがキューに渋滞しない程度のメッセージ数
・最大公約数的なメッセージサイズ
・キューのブロッキング動作は作成時に決定

という設計が必要だ。加えて落とし穴が1つあって、

・mq_receive()のバッファサイズはメッセージサイズ以上

という制約がある。
メッセージサイズより小さいバッファを指定するとエラーを返す。

これさえ押さえておけば、割と簡単に使うことができる。
ただしプロセスが落ちてもカーネルバッファにキューのデータが残ることには注意が必要である。プロセス落ちからの再起動があるならキューの残存データは考慮しておこう。

まあ細かいこと言いだせば、シグナル通知とかforkしてパイプとかメモリマップトファイルとかあるにはあるのだが、赤の他人ならぬ他プロセスとのデータ交換を考えるなら、FIFOかキューかドメインソケットから選ぶことになるだろう。共有メモリは排他制御とCPU浪費対策が面倒だ。

API仕様の表面からは見えにくい罠にはまってしまった。

0
1
0

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
0
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?