プロセスってご存知ですか? OSにいるあいつです。
プロセスってなんとなくわかるけど深くは知らないのはそろそろヤバイなということで、この本を読み進めています。
はじめてのOSコードリーディング ~UNIX V6で学ぶカーネルのしくみ (Software Design plus)
- 作者: 青柳隆宏
- 出版社/メーカー: 技術評論社
- 発売日: 2013/01/09
- メディア: 単行本(ソフトカバー)
- 購入: 56人 クリック: 1,959回
- この商品を含むブログ (29件) を見る
今回はこの本の2~3章のプロセスの項目の理解を深めるために解説をしていきたいと思います。
※なお自分の理解が及ぶ範囲で説明をしているため内容が簡素化しています
※間違いがあればご指摘いただけるととても助かります
対象読者
- CPU/メモリが何のためにあるのか知っている
- Linux/Unixなどを触ったことがある
- プロセスという言葉を聞いたことがある
プロセスに入る前の予備知識
カーネルとシステムコール
いきなり重たそうなワードがでてきましたが、ここでは大筋ではないためさっくりとした説明をします。
さいしょに
OS上では様々なアプリが動いています。GoogleChromeとか、ExcelとかPhotoshopとか色々あります。
これらが動くためにはCPUが頑張って計算をしてくれて、メモリがデータを格納していなければいけません。
つまり、各アプリはCPUやメモリに命令を出して情報を渡したりもらったりする必要があります。
しかしアプリケーションごとに、メモリやCPUをいじるための仕組みを導入するのは作るのが面倒ですし、あるアプリが悪さをして他のアプリが使ってるメモリを無理やり奪うことをしてしまっては問題があります。
そこでOSにはメモリやCPUなどの制御装置の操作をするために、カーネルと呼ばれる機能を用意してくれています。
- ユーザープログラム:アプリのことです
- ライブラリ:複数のアプリが使ってる汎用的な機能です
上の図のように、アプリケーションはカーネルに対してシステムコールと呼ばれる命令を出すことで、カーネル越しにCPUに計算を頼んでいるわけです。
プロセスとは?
さて本題です。そもそもプロセスとは何でしょうか?
すごく簡単にいうと動いているアプリケーションを指します。
プロセスの起動
プロセスが起動されると下記の順番で処理が走ります。
- カーネルがファイルシステム内のファイル(プログラム)をメモリに読み込む
- プロセスにメモリを割り当てる
- プロセスは仮想アドレス空間を持ち割り当てられたメモリにアクセスする
物理・仮想アドレス空間
メモリはメモリアドレスとよばれる16進数の番地で管理されています。
番地には大きくわけて2つありそれぞれ仮想・物理で分けられています。
- 仮想アドレス
- 物理アドレス
プロセスが使う情報は物理メモリに格納され、それぞれ対応する物理アドレスが割り当てられています。しかし、実際にプロセスがメモリにアクセスする際は仮想アドレスと呼ばれる空間となります。
仮想アドレス空間
プロセスを起動すると、カーネルはプロセスごとに仮想アドレス空間を作成します。この中でメモリの番地を管理します。通常物理メモリはすべてユニークなメモリ番地を所有していますが、仮想アドレス空間においてはプロセス単位で分けられていますのでプロセスごとに同じメモリアドレスを保有することができます。
仮想メモリ空間は物理メモリ空間とマッピングされており、仮想アドレス空間は物理アドレスを保有します。そのためプロセスは仮想アドレスを経由して物理アドレスにアクセスするわけです。
引用元:イケてるエンジニアになろうシリーズ 〜メモリとプロセスとスレッド編〜 - もろず blog
なぜ直接物理アドレスにアクセスしないのか?
セキュリティの観点
プロセスが直接物理アドレスにアクセスすることを許容すると、自身と関係のないメモリにアクセスすることができるようになり、セキュリティ上好ましくありません。
また、そのプロセスに制御を許可したいメモリ空間を限定できるといったメリットもあります。
メモリの効率利用の観点
プロセスは長期間動くものもいれば、瞬間的に動くものまで多種多様です。そのため物理メモリを順番に使おうとしても、頻繁に開放したり、大きなメモリサイズを要求された場合、飛び飛びでデータが保存するようになり、細切れはあるけれど大きなメモリは確保できないといった問題が発生します。
そのため仮想メモリが複数の細切れになった物理メモリをつなぎ合わせ、プロセスから見ればあたかも順番に繋がったメモリ空間であるかのようにみせることが出来ます。
スワップ時のメリット
スワップとはメモリの代替として使うハードディスクの領域の事を示します。メモリ内データの一時退避場所です。また、メモリが増えすぎたために、データの一部をディスクに外出することをスワップアウトと呼びます。
もしプロセスが物理メモリアドレスを直接参照していると、スワップアウトが発生した場合は参照先がハードディスクになってしまうため、メモリにアクセスしてもデータを参照できない問題があります。その点仮想アドレス使用時であればスワップアウト時のデータの移動先も管理できます。
CPUが処理できるプロセス数は1つ
1つのOS上には複数のプロセスが起動しています。しかしCPUが一度に処理できるプロセスは1つのみです。 シングルコアの場合
しかし、普段OSを使ってる限りは常に複数のプロセスが同時に動いているように見えます。その理由は、CPUが非常に速い速度で処理するプロセスを切り替えて、あたかも並列で動いているかのようにしているためです。
またデュアルコアやクアッドコアなどは、そもそもCPUが一度に処理できるプロセスを2倍、4倍に増やすものですし、サーバーではそもそも搭載するCPUを増やすことで処理可能なプロセスをふやしています。
プロセスを切り替える
CPUが一度に処理できるプロセス数は1つだという話をしました。そしてプロセスは頻繁に切り替えられているということもお話しました。実はこの時、プロセス単位で作成されている仮想アドレス空間も切り替わっています。
仮想アドレス空間は同一のアドレスを許容していますので、プロセス切り替わった時にこれも切り替わらないと別のデータにアクセスしてしまいますよね。
そこでMMU(MemoryManagementUnit)と呼ばれるハードウェアがプロセスが切り替わるごとに仮想アドレス空間を切り替えています。
プロセスの制御
プロセスのライフサイクル
さて、続いてはプロセスの生成について見ていきましょう。
プロセスの典型的なライフサイクルは以下の通りです。
あるプロセス(親プロセス)がforkシステムコールを発行して、新しいプロセス(子プロセス)を作成します
親プロセスはwaitシステムコールを発行し、子プロセスの終了を待ちます
子プロセスに制御が移ると、子プロセスはexecシステムコールを発行してプログラムをメモリに読み込み、そのプログラムを実行するプロセスへと変化します
子プロセスはプログラムを実行し終えるとexitシステムコールを発行しゾンビ状態となり、親プロセスに制御が移ります
親プロセスは子プロセスから実行結果を受け取り、子プロセスの後始末をします
うーん、分かりづらいですね。餃子作りで例えます。
餃子作りで例えるプロセスのライフサイクル
親プロセスが餃子レシピプログラムを読み込んでます。今から餃子を作るようです。
材料をカットするまでは1人でやっていた親プロセスですが「皮作りと餡作りは並行して子供にやってほしいなー」ということで、2人子供を作ることにしました。なんと自分自身をコピーして子供を作るようです。
そして母親は休憩に入ります。その間、子供たちは各々が「皮の作り方」「餡の作り方」のレシピを読み込み自分自身を皮作り・餡作りマンに書きかえていきます。
その後、作業が終わると母親を起こし成果(皮と餡)を差し出し、母親に終了させられるのを待つ事となります。
うーん、母親鬼畜。
それぞれのシステムコールの役割
- forkシステムコール:自分自身の複製を作ります
- execシステムコール:自分自身を書き換えます
- exitシステムコール:プロセスを終了します
- wakeupシステムコール:休止状態のプロセスを起こします
- waitシステムコール:休止状態に移行します
さいごに
本を読んでまとめてみただけなのに、全然理解できていなくてこの記事を書くだけで相当苦労しました…。
不明瞭、不鮮明な点・誤りがあればご指摘いただけるととても助かります!
では。