コンピューターサイエンス:アルゴリズム / OS / ネットワーク / DB
プロセス間通信(IPC)
隣の家の冷蔵庫は、開けようとしても見つからない
プロセスには壁があり、他人の変数に手が届きません。ところが実際のシステムは、複数のプロセスで役割を分けて協力するものばかりです。データベースとアプリ、ブラウザと描画担当、ログを集める常駐サービス。壁を残したまま、どうやって物を渡すのか。そのための仕組みをまとめてプロセス間通信と呼びます。
壁を壊さずに渡す方法は、大きく分けると 3 つの発想しかありません。中継地点を用意する、壁に穴を開けて共有部屋を作る、外の道路を使って届ける、です。
気づかず毎日使っている中継地点
いちばん身近なのが、シェルの縦棒です。
ターミナル
ls -l | grep ".txt" | wc -lここでは 3 つのプロセスが立ち上がり、左の出力が右の入力に流れています。ファイルには一度も書いていません。カーネルがメモリ上にバッファを用意し、左が書き、右が読む。片方が速すぎれば自動的に待たされ、書き手が終われば読み手にも終わりが伝わります。これがパイプです。
血縁のないプロセス同士でも、名前を付けたパイプを作れば同じことができます。試すのが早いので、ターミナルを 2 枚開いて確かめてください。
ターミナル
mkfifo /tmp/myfifo
cat /tmp/myfifo # 1 枚目、ここで待つ
echo "hello" > /tmp/myfifo # 2 枚目、こう打つと 1 枚目に出るもう 1 つ、日常的に使っている口があります。Ctrl+C です。あれはシグナルという通知を相手のプロセスへ送る操作で、kill コマンドで送っているものと同じです。ただしシグナルは合図しか運べません。「終わってほしい」は伝えられても、データは渡せません。
速さが要るなら壁に穴を、遠くへ届けるなら道路を
数百メガバイトの画像を毎秒渡したい、というときはパイプでも足りません。その場合は、両方のプロセスから見える共有の領域をカーネルに作ってもらい、そこへ直接置きます。中継地点を経由しないぶん、いちばん速い方法です。
代償もあります。共有した領域には壁が無いので、片方が書いている途中でもう片方が読むと、半端な状態を掴みます。誰がいつ触ってよいかの取り決めを、自分たちで設計しなければなりません。速さと引き換えに、事故の責任を引き受ける形です。
相手が別の機械にいるなら、ソケットを使います。同じ機械の中だけで使う専用のソケットもあり、ファイルのパスで相手を指定できます。データベースやコンテナ基盤が既定でこれを使うのは、TCP を経由するより速く、しかもネットワークに露出しないからです。
ローカルのパイプや共有領域は、毎秒ギガバイト級の帯域が出ます。プロセス間通信が遅いというのは思い込みで、遅くなるのはネットワークを跨いだときだけです。
選ぶときの順番は、速さからではありません。まず「合図だけで足りるか、データを運ぶのか」を分け、運ぶなら「相手は同じ機械にいるか」を見ます。同じ機械の中で流れが一方向なら、まずパイプで足ります。それで間に合わなくなってから、共有領域を検討してください。最初から最速の手を選ぶと、取り決めを自分で設計する重さだけが先に乗ってきます。