プロセス
出典: フリー百科事典『ウィキペディア(Wikipedia)』
プロセス(process)とは、英語で過程を意味する言葉。
- 工業製品の製造工程。
- 特に、半導体の製造工程を言う。集積回路の細密度につき、10nmプロセスなどと言う。
- 品質管理上の概念。プロセスアプローチ。
- コンピュータにおける処理の単位の一つ(本稿で詳述)。
- ソフトウェア開発プロセスの略称。
- やしきたかじんのアルバムタイトル。
プロセスとは、情報処理においてプログラムの動作中のインスタンスを意味し、全ての変数やその他の状態を含む。マルチタスクオペレーティングシステムでは多くのプロセスを並列実行するためにプロセス間でコンテキストスイッチを行うことがある。スレッドとは異なり、OSから記憶領域やディスク資源を割り当てられて、処理を実行する。
組み込みシステムのオペレーティングシステムでは、プロセスをタスクと呼ぶことが多い。「プロセス」(あるいはタスク)という用語は「時間を占める何か」であり、対照的に「メモリ」は「空間を占める何か」である。タスクという語は、タスク=スレッドの意味で使われることもあり、プロセスという語より適用範囲が広い。また、ジョブがユーザーから見た処理の単位であるのに対し、「プロセス」は、コンピュータ側から見た処理の単位。
ひとつのCPUスレッドにおいてはある一時点にひとつのプロセスしか実行できない。Athlon 64 X2のようなデュアルコアのプロセッサでは、2つのプロセスを一度に実行することができる。インテルのPentium 4での同時マルチスレッディングはそれとは異なる設計である。マルチスレッドでないプロセスに関して言えば、メモリレイテンシを隠蔽することによってコンテキストスイッチを高速化する効果が期待できる。
主プログラムを1つのプロセスとし、それ以外を並列に動作するプロセス群として独立させ、非同期に動作するサブルーチンとして実装することもある。プロセスはリソースを所有しており、メモリ上のプログラムの「イメージ」はそのようなリソースの1つと言える。マルチプロセッシングシステムでは多くのプロセスが同じリエントラントなプログラムのメモリ上のコピーを共有しているが、プログラムの「イメージ」は個々のプロセスが所有していると言える(多重仮想記憶)。
以上の説明はオペレーティングシステムに管理されるプロセスにも、プロセス代数で定義されるプロセスにも当てはまる。
目次 |
[編集] プロセスの構成
オペレーティングシステムはプロセス同士を分離させておいて必要なリソースを割り当て、プロセス間で互いに干渉しあってシステム障害を発生(例えば、デッドロックやスラッシング)したりしないようにする。オペレーティングシステムはプロセス間通信の機構も用意してプロセスが安全に通信し合えるようにしている。
一般に、プロセスは以下のようなリソースから構成される(あるいは所有している):
- プログラムに対応する実行命令コードの「イメージ」
- メモリ(通常、仮想メモリの領域と実メモリの領域)には実行コードとプロセス固有データを格納している。
- プロセスに割り当てられたリソースの記述子。例えば、ファイル記述子(UNIX系)やファイルハンドル(Windows)。
- セキュリティ属性。プロセスの所有者やプロセスに関わるパーミッションなど。
- プロセッサ状態(コンテキスト)。レジスタの内容、物理メモリのアドレシングなど。「状態」はプロセス実行中はレジスタに存在し、そうでないときはメモリに存在する。
これらリソースの一部、少なくともプロセッサの状態情報は、プロセスというよりもスレッドに対応している。
プロセスが中断された状態ならば、ディスクにスワップアウトすることができるが、仮想記憶システムではこれは透過的であって、あるメモリブロックの内容がディスク上にあってメモリ上にないという状態は正常な状態である。動作中プロセスの「未使用」部分もディスクにスワップアウト(ページアウト)することができる。実行中プログラムやそのデータのいかなる部分も、対応するプロセスを実行するにあたって物理メモリ上に存在する必要はない。しかし、プロセスがディスク上のコードやデータを必要としたとき(対応する仮想アドレスにアクセスしようとしたとき)、実行が中断されてページングとして知られている方法でその内容が物理メモリに移動される。
[編集] プロセスの分類
プロセスは、その役割で分類すると、OSの機能を実現するシステムプロセスと、ユーザー権限で実行されるユーザープロセスがある。
プロセスは、そのプログラム部分の性質で分類すると、以下のようになる。
- 再配置可能(リロケータブル)
- プロセスを補助記憶装置から主記憶装置に読み込む際、主記憶のどの位置に読み込んでも実行が可能なプログラム。アドレス指定が、プロセスの先頭アドレスからの相対位置で表現されていればよい。リロケータブルコードのうち、特にポジションインディペンデント(位置非依存)コードと呼ばれるものは、リンカやローダの機能に依らずとも自由な位置での実行が可能なコードであり、単にリロケータブルであるものとは区別される。
- 再使用可能(リユーザブル)
- 主記憶に読み込まれて実行を終えたプログラムが、再度の主記憶への読み込みを行うことなく再実行できることをいう。これには、実行し終えたプログラムをプログラム自身が書き換えない。実行後にプログラム内部変数に影響が残ってしまわないことなどが必要である。
- 再帰可能(リカーシブル)
- 自分自身を呼び出すこと(再帰)が可能なもの。
- 再入可能(リエントラント)
- プログラムの実行中、別のプロセスが同じプログラムを同時に実行できるもの。プログラム(コード)部分とデータ部分が別の記憶領域に分かれていて、コード部分だけ共有できればよい。同時実行したいプロセスは、データ部分だけ独自に新しく用意する。リエントラントなコードは、当然にリカーシブル、リユーザブルである。
[編集] 歴史
コンピュータ制御ソフトウェアはモニター制御ソフトウェアから進化し、マルチプログラミングが可能となった。マルチプログラミングはマルチプロセッシングの初歩的な形態であり、ひとつのプロセッサ上で「並列」にいくつかのプログラムを実行するものである。すなわち、いくつかのプログラムがCPUという限りあるリソースを共有する。プロセッサは1つなので、本当に同時に複数のプログラムを実行できたわけではない。初期のオペレーティングシステムはリソース待ち(入力待ちなど)で停止するまでひとつのプログラムを実行するか、遅い操作(出力など)が終わるまで別のプログラムの実行をするようになっていた。そのような入出力待ちなどの時点でプログラムを切り換えていたのである。これをユーザーから見ると、全てのプログラムが「同時に」実行されているように見えた。
間もなく「プログラム」の観念は「実行中プログラムとそのコンテキスト」という観念に拡張された。これがプロセスという概念の誕生である。スレッドという概念が生まれるのはその少し後になる。タイムシェアリングシステム、コンピュータネットワーク、マルチプロセッサ、メモリ共有型コンピュータなどが登場し、古い「マルチプログラミング」は真のマルチタスクやマルチプロセッシングにとって代わられ、さらにはマルチスレッドへと進化していったのである。
[編集] プロセスの状態遷移
マルチタスクコンピュータシステムでは、プロセスは様々な状態を呈する。これらの状態はオペレーティングシステムのカーネルでは明確に認識されないかもしれないが、抽象化することでプロセスを理解するのが容易になる。
以下の典型的なプロセス状態は多くのコンピュータシステム上で見られる。これらの状態のほとんどで、プロセスはメインメモリ上に存在する。
[編集] 生成
プロセスが最初に作成されると、生成(created)状態あるいは新規(new)状態となる。この状態ではプロセスは走行可能状態にされるのを待つ。この状態遷移をさせるのはスケジューラである。多くのシステムではこの遷移が自動的に(即座に)行われるが、リアルタイムオペレーティングシステムでは遅延が生じることがある。リアルタイムシステムで多くのプロセスを走行可能状態にしてしまうと、過飽和とシステムリソースの競合が発生し、プロセスのリアルタイム性を損なってしまう。
[編集] 走行可能
走行可能(ready)状態あるいはスケジュール待ち(waiting)状態のプロセスはメインメモリにロードされCPUによる実行を待っている(ディスパッチャか短期スケジューラによってCPU上にコンテキストスイッチされるのを待っている)。任意の時点の走行可能状態のプロセスは非常に多数になる可能性がある。例えば、プロセッサが1個のシステムでは一度にひとつのプロセスしか実行できないので、他のプロセスの多くは実行されるのを待っている状態となる。
[編集] 走行中
走行中(runnning)状態、実行中(executing)状態、活性(active)状態などと呼ばれる。この状態のプロセスは現にCPU上で実行されている。この状態で割り当てられたタイムスライスを使い切ると走行可能状態に戻される。あるいはプログラムの実行が終了すれば終了状態になるし、何らかのリソースが必要になればブロック状態になるだろう。
[編集] ブロック状態
スリープ(sleeping)状態ともいう。プロセスはリソース(ファイル、セマフォ、周辺機器など)を確保できないと、プログラム実行を続けられなくなるのでCPUから外されてブロック(blocked)状態となる。プロセスはそのリソースが利用可能となるまでブロック状態のままとなるが、これがデッドロック状態を発生させることもある。ブロック状態のプロセスに対してオペレーティングシステムはリソースが利用可能となったことを知らせる(オペレーティングシステム自体は割り込みによってリソースが利用可能となったことを知る)。オペレーティングシステムはブロックされなくなったプロセスを再び走行可能状態にし、そこから走行中状態にディスパッチされると、プロセスは利用可能となったリソースを使用することになる。
[編集] 終了状態
プロセスは走行中状態でプログラムの実行完了によって終了状態となるか、明示的に終了させられることもある。どちらの場合でもプロセスは終了(terminated)状態になる。プロセスがこの状態になってもメモリから消去されない場合、この状態をゾンビ(zombie)状態とも呼ぶ。
UNIX系オペレーティングシステムにおいて、ゾンビプロセス(Zombie Process)は、処理を完了したがプロセステーブル(プロセス制御ブロック相当)が残っていて、終了ステータスを読まれるのを待っているプロセスである。この用語のメタファーに従えば、ゾンビプロセスは「死んでいる」が、まだ「死神」が到着していないということになる。
プロセスは終了するときに、使用していた全メモリとリソースを解放して他のプロセスが再利用できるようにする。しかし、プロセステーブルのエントリは残される。親プロセスには子プロセスの終了を知らせるために SIGCHLD シグナルが送られる。親プロセスは SIGCHLD シグナルを必ずしも利用する必要はなく、利用するかどうかはプログラミングの都合による。親プロセスが子プロセスをゾンビ・プロセスにせずに「見取る」ためには、子プロセスの終了ステータスを読み取ってゾンビを削除する。一般的にはプログラムの適当な場所で waitpid
システムコールを WNOHANG オプションつきで呼び出すか、シグナル・ハンドラで SIGCHLD を補足し wait
を実行するか、または signal
もしくは sigaction
システム・コールで SIGCHLD に対して SIG_IGN シグナル・ハンドラを設定する方法が代表的である(SIGCHLD に対し SIG_IGN を設定する方法は POSIX.1-1990 では認められていなかったが、POSIX.1-2001 で認められるようになった)。ゾンビの使用しているプロセス識別子とプロセステーブルエントリがそれによって再利用可能となる。このような処理を行わなければゾンビプロセスは残存し続ける。例えば、親プロセスが他の子プロセスを生成しようとしていて、ゾンビとなっているプロセスと同じプロセス識別子を割り当てられたくないときなどは、ゾンビプロセスを残す意味があるだろう。
ゾンビプロセスは孤児プロセスと同じではない。孤児プロセスはゾンビ状態にはなっておらず、init
プロセスを里親としているので必ず wait
が実行される。
ゾンビプロセスは UNIX の ps コマンドの STAT カラムに "Z" と表示されることで識別される。ゾンビプロセスは一般に非常に短期間しか存在しないが、親プロセスのプログラムにバグがあるとずっと残存することがある。メモリリークと同様、ゾンビプロセスが多少存在しても問題はないが、高負荷状態でゾンビが増えるとプロセスを生成できないなどの問題を発生することになる。
ゾンビプロセスを消去するには、まず親プロセスに kill コマンドで SIGCHLD シグナルを送ってみる。これで親プロセスがゾンビを刈り取らないなら、次は親プロセスを終了させる。プロセスは親プロセスが終了すると init が新たな親に設定される。init は定期的に wait
システムコールを実行しているので、全てのゾンビプロセスを刈り取ってくれる。
[編集] その他のプロセス状態
仮想記憶をサポートするシステムでは、上記以外に2つの状態がある。どちらの状態もプロセスは二次記憶装置(ハードディスクなど)に格納される。
ひとつは、スワップアウト(またはサスペンド)されたスケジュール待ち状態である。仮想記憶をサポートするシステムでは、プロセスはスワップアウトされることがあり、中期スケジューラがメインメモリから仮想メモリに移動させる。その後、中期スケジューラによってスワップインされ、通常のスケジュール待ち状態になる。
もうひとつは、スワップアウト(またはサスペンド)されたブロック状態である。ブロックされたプロセスもスワップアウトされることがある。この状態ではプロセスはスワップアウトされた上にブロックされているため、先にスワップインされれば通常のブロック状態になるし、先にリソースが利用可能になればスワップアウトされたスケジュール待ち状態になる。