毎週 1冊技術書を読んでブログでアウトプットするチャレンジの第5弾ですーー!
なんとか続いています、、、!習慣になってきた、、、!
今回は、なるほどUnixプロセス Rubyで学ぶUnixの基礎 を読みました。
読む前は、Unix?プロセス?? というお恥ずかしい状態だったのですが、本書を2周読み終えた今、少しずつ理解できてきました。
少しとっつきにくい内容かもしれませんが、知っていて損ではない内容だと思うので是非見てみてください。
- 第3章 プロセスにはIDがある
- 第4章 プロセスには親がいる
- 第5章 プロセスにはファイルディスクリプタがある
- 第6章 プロセスにはリソースの制限がある
- 第7章 プロセスには環境がある
- 第8章 プロセスには定数がある
- 第9章 プロセスには名前がある
- 第10章 プロセスには終了コードがある
- 第11章 プロセスは子プロセスを作れる
- 第12章 孤児プロセス
- 第13章 プロセスは優しい
- 第14章 プロセスは待てる
- 第16章 プロセスはシグナルを受信できる
- 第17章 プロセスは通信できる
- 第18章 デーモンプロセス
- 第19章 端末プロセスを作る
- 第20章 おわりに
- 付録A Resqueのプロセス管理
- 付録B Unicornのワーカープロセスの管理
- 付録C preforkサーバ
- おわりに
第3章 プロセスにはIDがある
-
システムで動作するすべてのプロセスは固有の識別子(プロセスID)があり、pidと呼ばれている
-
pidはプロセスにまつわる情報は何も持たずに、単に連番になっている数値のラベルである
-
pidはログファイルで有効に使われている。pidにより、ログファイルの各行がどのプロセスから出力されたものかを識別できる
第4章 プロセスには親がいる
-
親プロセスはそのプロセスを起動したプロセスである
第5章 プロセスにはファイルディスクリプタがある
-
実行中のプロセスでリソースを開くと、ファイルディスクリプタ番号が割り当てられる
第6章 プロセスにはリソースの制限がある
-
カーネルによって1プロセスごとにリソースの制限が設定されている
-
制限は設定を変更することでほぼ無限大にすることができる
第7章 プロセスには環境がある
第8章 プロセスには定数がある
-
RubyプロセスはARGVという特別な配列を参照できる
-
argvとは引数の配列を意味するargument vectorの略である
-
argvにはコマンドラインからプロセスに渡された引数が格納されている
-
プログラムにファイル名を渡したいケースにARGVが最もよく使われる
第9章 プロセスには名前がある
-
Unixプロセスにはプロセスの状態を知らせるための手段がほとんどなく、これを回避するためにログファイルを作成した
-
プロセスのレベルで情報を伝えるための仕組みは二つあり、一つはプロセス名でもう一つは終了コードである
第10章 プロセスには終了コードがある
-
慣習としてプロセスは正常終了時には終了コード0を返す。それ以外の終了コードはエラーを示しており、終了コードごとに異なるエラーの種類を表す
-
raiseで送出された例外が捕捉されない場合もプロセスは終了する
第11章 プロセスは子プロセスを作れる
-
fork(2)で子プロセスを生成すると、実行中のプロセスの完全なコピーを生成でき、親プロセスで使われている全てのメモリのコピーを受け継ぐ
第12章 孤児プロセス
-
親プロセスが死んでも子プロセスは生き続ける
-
デーモンプロセスとは意図的に孤児化されたプロセスであり、いつまでも動き続けることを狙いとしている
第13章 プロセスは優しい
-
fork(2)は親プロセスの完全なコピーを新しい子プロセスとして生成するが、物理的に全てのデータをコピーするのはかなりのオーバーヘッドになるため、コピー・オン・ライト(CoW)と呼ばれる仕組みを採用している
-
CoWは書き込みが必要となるまでメモリを実際にコピーしない。それまでの間、親プロセスと子プロセスとはメモリ上の同じデータを物理的に共有しており、親または子のいずれかで変更する必要が生じた時のみメモリをコピーすることで両者のプロセスの独立性を保っている
-
CoWはfork(2)で子プロセスを生成するときにリソースを節約できるのでとても便利な仕組みである
第14章 プロセスは待てる
-
孤児プロセスが発生しないようにProcess.waitを使えば、子プロセスのいずれか1つが終了するまで親プロセスをブロックして待つことができる
-
子プロセスを活用するのは、Unixプログラミングでよく使われるパターンである。こうしたパターンは子守りプロセスやマスター/ワーカー、preforkなどと呼ばれている
-
このパターンの肝は用意した1つのプロセスから並列処理のために複数の子プロセスを生成して、その後は子プロセスの面倒を見るというもの。子プロセスたちが応答するのかを確かめたり、子プロセスが終了した際には後始末をする
第16章 プロセスはシグナルを受信できる
-
シグナルは非同期通信。プロセスはカーネル(OSの核となるプログラムで複数のプロセスを同時に実行するためのスケジュール管理やメモリの管理を行うもの)からシグナルを受けたとき、①シグナルを無視する、②特定の処理を行う、③デフォルトの処理を行う、のいずれかの処理を行う
-
シグナルはある特定のプロセスから別のプロセスへと送られるものであり、カーネルはその仲介役となっている
-
pidさえ分かれば、システム上のどのプロセスともシグナルで通信できる。シグナルはプロセス間の通信手段である
-
現実世界でのシグナルは、サーバやデーモンといった長期間動き続けるプロセスで使われているのがほとんどである
第17章 プロセスは通信できる
-
プロセス間通信(IPC)で複数のプロセス間で情報をやりとりできる
-
パイプは単方向のデータの流れ。パイプを開くというのは、プロセスの片方の端を別のプロセスの片方の端につなぐことをいう。パイプを通じてデータを流すことができるようになるが、その方向は単方向に限られる。プロセスがパイプに対して書き込みではなく読み込み側となることを宣言した場合、そのパイプには書き込めない。逆も然り
-
パイプが単方向の通信手段であるのに対し、ソケットは双方向の通信手段である。親のソケットは子のソケットに読み書きできるし、逆も然り
第18章 デーモンプロセス
-
デーモンプロセスは、ユーザーに端末から制御されるのではなく、バックグラウンドで動作するプロセスである。デーモンプロセスのよくある例としては、Webサーバやデータベースサーバのように、リクエストをさばくためにバックグラウンドで常に動作するプロセスがある
-
デーモンプロセスはオペレーティングシステムの核でもある。さまざまなプロセスがバックグラウンドでずっと動作し続けているおかげで、システムは正常に動いている
-
プロセスを永遠に応答し続けられる状態にする必要がある場合にデーモンプロセスを用い、不要ならcronジョブなどのバックグラウンドジョブの仕組みを検討する
第19章 端末プロセスを作る
-
execve(2)によるプロセスの置き換えは元に戻すことができない
-
fork + execveの組み合わせは新しくプロセスを生成する際によく使われる。fork(2)で新しく子プロセスを生成して、それからその子プロセスを任意のプロセスに置き換えるためにexecve(2)を使う
第20章 おわりに
-
シグナルを使えば、システム上のどんなプロセスも互いに情報を伝達できる。プロセスに名前を付けることで、コマンドライン上から誰でもプログラムの状況を検査できる。終了コードを使えば、呼び出し元のプロセスに成功/失敗のメッセージを伝えられる
付録A Resqueのプロセス管理
-
ResqueはRuby製の有名なジョブキューである
-
Resqueワーカーの仕事は、起動してアプリケーション環境を読み込んだらRedisに接続し、保留中のバックグラウンド・ジョブの実行を予約すること
-
Resqueワーカーはメモリ管理のためにfork(2)を使っている。Resqueはfork(2)を使うことで、ワーカープロセスのメモリ使用量が肥大化しないようにしている。Resqueがジョブを実行した後、メモリの使用状況は毎回ジョブの処理を行う前のきれいな状態に戻っている。メモリ解放の仕組みであるGC(ガベージコレクション)には課題があるため、fork(2)を使う方がメモリの使用量を抑えることができる
付録B Unicornのワーカープロセスの管理
付録C preforkサーバ
-
preforkは複数のプロセスを個別に生成するよりもメモリを効率的に使うことができる
おわりに
いかがでしたでしょうか。馴染みのない言葉ばかり出てくるので難しいですよね。
粘り強く読書を継続して、知識をつけていきましょう、、、!
引き続き、こちら(↓)の記事で紹介した本を順番にアウトプットしていく予定です。
是非参考にしてみてくださいー!
来週もよろしくお願いします!