プロセスその1
次のお題はProcessに関連する部分だ。第6章(上巻P339)からがメインといえばメインなのだが、この中身に入る前にすこし前提となる話をする必要があるだろう。
現在のWindows NTにおいて、プログラムの最小実行単位はThreadということになっている。このThreadという概念はWindows NT 3.1ですでに実装されており、更にWindows NT 3.51 SP3ではFiber(LWT:Light Weight Thread)のサポートが追加されており、そうした意味では早い時期からThreadをサポートしたOSという事になる。ただ、Threadという概念が広く利用されるようになったのは、割と最近のことである。
Threadは、最初はLWP(Light Weight Process)という名前で呼ばれていた。最初にこの概念を提唱したのは、David Cheritonらの論文である"Thoth, a Portable Real-Time Operating System"ではないかと思うが、これを実際に採用した大きなものは、Machオペレーティングシステムである。Machに採用されたことで、主要なOSが次々とこの概念を取り入れるに至った。筆者の場合、最初にThreadに触れることになったのは"Sun OS 5.0"の説明会が最初である(当時はまだSolarisなんて名前になってなかった)。VMSにしても、Version 5.2の段階ではまだThreadの影も形もない。ただその後はDECthreadsなんて名前でThreadのサポートが追加されているので、後から追加されたことは間違いない様だ。もっとも、VMS上でのThreadというと、しばしば"Main ThreadとAST Thread"なんて記述があったりして、これは厳密に言えばThreadでは無いのだが、このあたりを突っ込み始めるとキリが無いのでここでは割愛する。
さて話を戻すが、VMSとかWindows NT「以前の」Windows、あるいはMach以前のUNIXなどでは、処理の最小単位はProcessという事になっている。実はNTにおいても、メモリ空間の割り当てなどに関して言えば、今でもProcessが最小単位である。ただ、プログラムの実行コンテクストに関して言えば、1つのProcessに対して同時に複数のCPUが割り当てられ、実行されるという状況が発生するようになり、これを管理するにはProcessではうまく行かないということで、CPUリソースに関してのみThreadで管理するという形になったのが最初で、更にThreadですら生成のリソースが大きすぎるということでLWTが追加されたという形だ。ただ、LWTに関してはOSにより実装はまちまちで、たとえばWindows NT系の場合Fiberの実行制御はアプリケーションが握る形になっており(上巻P15)、従ってProcess/Thread制御とは直接無関係という扱いになっているのが普通だ。
で、話をProcess/Threadに移すと、初期のOS(Windows NT以前)におけるThreadの扱いは図1の様な構造になっていた。つまりCPU時間を割り当てる場合、まずProcess単位でラウンドロビンなりPriority制御なりでTime Slotを割り振り、更にそのプロセスが複数Threadに分割されている場合には、各Processに割り当てられたTime Slotを分割して各Threadに割り当てるという方法である。実はSingle CPUの構成では、これは概ね上手く動作した。Thread毎にCPU時間を割り当てる作業はオーバーヘッドが多くなる(たとえば筆者の手元のWindows XPマシンのタスクマネージャを開いてみると、プロセスは全部で74存在するが(Photo01)、スレッドは790にも及ぶ(Photo02)。74個のContext Switchingと790個のContext Switching、どちらがオーバーヘッドが多いかは言うまでもない。ただこれだと、マルチCPU環境におけるメリットがあまり無い。そこで、昨今のOSの場合は図2の様なThread管理を行うのが普通である。つまりThreadレベルでCPU時間の割り当てを行うという方式だ。Windows NTもこちらを採用しており、このあたりはVersion 5.2のVMSと大きく異なる部分である。まぁこれはそもそもVMSにThreadの概念が無かったから当然でもあるのだが。ただ、大きく異なるのはThreadとProcessの違いであり、逆に言えばThreadをProcessと読み替えるとかなりVMSに近くなる。
もう一つ、互換性に起因する違いがいくつかある。VMSの場合、原則としてVMS用に記述されたプログラムしか動かない(*1)から、Process生成はそれほど面倒ではないのだが、Windows NTでは様々なプログラムを動かす必要があり、このためCreateProcess()関数が様々なサブシステムを呼び出す場合がある(上巻P354)。またVMSはもともとがコマンドライン向けプログラムだったから、プロセスの生成といってもそれほど面倒な話ではないのだが、WindowsはGUIを前提にした環境だから、ウィンドウオブジェクトを作成するのが前提となる。この結果、Processの管理がWindowHandle経由という話になるのもちょっと異なる部分だ。ただ6.2.2(上巻P356~)を追うと判るとおり、Windows kernelの内部はWindow HandleではなくProcess Objectとして各Processを管理しており、この限りにおいてはVMSとそれほど違いが無いとは言えるが。(続く)
(*1) PDP-11という16bitのプログラムを動かす互換モードが用意されており、これを使う時のみ、ちょっと話が変わってくる。