bekkou68 の日記

Gogengo! や IT 技術など。

『Working with Unix Processes』の Processes Can Communicate を読みました

はじめに

Processes Can Get Signals の続きです。だいぶ終盤になってきました。

まとめ

プロセス間コミュニケーション(IPC)の一般的な方法はパイプとソケットがある。パイプは単方向。パイプはファイルディスクリプタをもつリソースなので子プロセス間でシェアできる。ソケットは双方向。Unixのソケットは物理的に1台のマシン内で通信するためのもの。
マシンを超えて IPCしたければ TCPソケット・RPC・zeromq などを使う。
Spyglass の Masterクラスでは複数の子プロセスが 1つのパイプで親プロセスと通信しているコードが書かれている。

ストリーム vs メッセージ

ストリームとメッセージの違いは以下のようなイメージなのですが合ってるのかなあ。

  • ストリーム: パイプで通信する。EOF や改行などといったデリミタがある。明確な終わりがない。アナログのような流れている感じ? ストリームなだけに
  • メッセージ: ソケットで通信する。デリミタがない。明確な終わりがある。デジタルのようなぶつ切りな感じ?

疑問

今回は出てきた疑問の数がいままでで一番多かったです。わかったことはもちろんありましたが出てきた疑問の方が多かったような気がしますw

なぜそのタイミングで close しているのか

本文中の「親子プロセス間でパイプを共有する」コードの例で、close のタイミングがなぜそこなのかがちゃんと理解できてないです。何となくの理解としては、fork するタイミングで writer, reader がそれぞれのプロセスで作られるため、片方の writer.write するときには reader.close して、もう片方で reader.read するときには writer.close しないとブロックしてしまうからだとは思ってます。内部の動作がどうなっているのかもっとイメージできるようになりたいです。
この疑問を解決するにはこちらの文献を読むのがいいかもと思っています。まだちゃんと読んでないですが。『UNIX 6th code reading - パイプ - やる気のないはてだ

上記の疑問を解決するときの手段として

Ruby のコードで、そのオブジェクトが CoW して作られたかどうかって確認できるのかなあ? fork した中で object_id を取得しても親子で同じだったのですが、CoW して作られたものだから object_id は違うけど、アドレスは違うということなのですかね。アドレスが違うことはどうやって Ruby のコードで確認できるのかなあ?

パイプは何のために存在しているのか

ソケットが双方向通信できるのならパイプはいらないのでは? という短絡的な疑問がわきおこりました。調べてはみたのですがパイプの存在意義がまだよくわかりません。たぶん、パイプにできてソケットにできないことは、複数プロセスから write することなのかなと思っています。ソケットは 1つのプロセスがつかまえたら終わり。そういう使い分けをするのかな? あとは、パイプは単方向でソケットは双方向なので、通信の方向がどちらなのかという意図を示すのに使い分けたりするのでしょうか。わかりません><
I/O システム』によると "パイプとソケットの大きな違いは、 パイプは共通の親プロセスが設定する必要があるのに対して、 ソケットはまったく無関係の (異なるマシン上で動作する) プロセス間でも使用できる点" なので、そういう使い分けなのかなあと思いつつ。ただ、もっと調べていったら、名前付きパイプはソケットのようにふるまうらしいです。普段つかっているパイプは無名パイプだそうで。もう何が何やら…。

Ruby の IOクラスについて

IO の reader と writer の動作切り替えはどうやってやってるのかな。オブジェクトで mode を持っているのかな。Unixシステムコールをたたいた結果を返しているのかな。

調べたこと

Ruby の IOクラスにおいて。

  • read: デリミタは EOF
  • gets: デリミタは改行

フレーズ

  • ...vice versa: ...もそうだし逆も同じ
  • boilerplate code: お決まりのコード
  • plausible solution: もっともなソリューション

感想

サンプルコードに "Another one bites the bust" とあってクスッときました。QUEEN歓喜^^ ところで "bites the dust" で「屈辱を受ける」・「死ぬ」という意味があります。やはり「ゴミを喰らう」から派生した意味でしょうか。強烈な語源ですねえ。
コマンドラインでパイプをよく使っていたのですが、同様のことを Ruby の IO.pipe でできるのかあと思い、頭のなかでつながっていく感じがありました。fork がからむと途端にワケがわからなくなるので整理して理解できるようになりたいなあ。
今回で疑問がものすごく出たということは考える視点が広がったことであるとポジティブにとらえて、少しずつ聞いたり調べたりして腹に落としていこうと思いました。