OSの一番核となる機能と言えばプロセス管理。Windows OSの内部ではプロセスやスレッドはどのように動作しているのか、GUIアプリケーションのパフォーマンスなどを改善する優先度/クォンタムブースト、マルチコアCPUの性能を引き出すスレッドスケジューリングやアフィニティ設定などについて解説。
前回はWindowsのリソース管理などで利用される「アクセス制御リスト」について取り上げた。今回はWindows OSカーネルを理解するための第一歩として、プロセスとスレッドについて見ていこう。
Windows OSの動作状態を確認する場合、通常は「タスク マネージャー」を起動するだろう(関連記事参照)。この小さなツールには、現在のWindowsシステム内で動作しているプロセスやサービスの動作状況、メモリの利用状況、システムの負荷や動作状況、リソースの利用状況などが適正かどうかを判断するためのさまざまな情報が表示されている。今回はタスクマネージャーで表示されているさまざまな項目のうち、「プロセス」と「スレッド」に注目してWindows OSの中を見てみよう。
画面の一番下を見ると、このシステムでは現在「140」個のプロセスが動作していることが分かる。Windows OSのバージョンやシステム構成、利用状況などにもよるが、1台のシステムでは、数十〜数百ものプロセスが動作している。
といっても実際に全てのプロセスが常に「実行」中というわけではなく、ほとんどの場合は「実行可能な状態」で待機しているだけである。左上にある「CPU 使用率」の表示が100%になったり、さらにそれがずっと続いているというようなことは滅多にないはずだ。Windows OSの場合は、ユーザーの入力待ちとかデバイスに対する入出力要求の完了待ち、(トリガーとなる)イベント待ち、などとなっていることが多い。
ではなぜこのように多数のプロセスがあるかというと、プロセスがプログラムの実行単位となっているからだ。さまざまな理由により、1つのアプリケーションは通常1つ、ないしは複数の実行ファイル(プログラム。通常は.EXEファイル)を組み合わせて構成されている。そのため、ユーザーが起動しているアプリケーションが増えたり、[スタートアップ]メニューやサービスに多数のアプリケーションを登録していると、それだけ起動しているプロセスの数も増える。ユーザーが明示的にインストールしたものでなくても、アプリケーションのインストールや更新などに伴って知らないうちにインストールされているものも少なくない。そのため、長くWindowsシステムを使っていると、非常に多くのプロセスが動作することになる。
「プロセス(process)」とは、Windows OSにおけるプログラムの実行単位である。ユーザーが何らかのアプリケーションを起動すると、それは実際には1つ以上のプロセスが起動することになる。プロセスの実行イメージやデータなどは通常「〜.EXE」という名前のファイルに格納されている。プロセスを起動しようとすると、.EXEファイル中に格納されている実行コードやデータ、リソースなどのイメージがメモリ上に展開され、それを呼び出すようになっている(実際にメモリ上にどのように展開されるかについては次回解説予定)。
実行中のプロセスと実行ファイルとの対応や、各プロセスのID、プロセスの説明、使用中のメモリサイズ、動作状態、優先度、使用中のリソースハンドルの数などの情報は、タスクマネージャーの「プロセス」タブの内容を見れば分かる。Windows 8/Windows Server 2012以降のタスクマネージャーの場合は、「プロセス」タブでは概要のみが表示され、より詳しい情報は「詳細」タブで確認するようになっている。
実際のプロセスの状態を次の画面に示しておく。これは「プロセス」タブを選択後、[表示]メニューの[列の選択]で、実行中のプロセスに関するさまざまな情報を表示させたところだ。
プロセスに関する各項目の意味は次の通りである。
項目 | 意味 |
---|---|
PID(プロセスID) | プロセスID。プロセスを識別する番号。0(System Idle Process)と4(System)はいつも同じだが、他のPIDは状況に応じて変わる。値の大小に特に意味はない |
ユーザー名 | どのユーザーアカウント権限で動作しているかを表す。OSカーネルのプロセスはSystemとなっているものが多い |
セッションID | セッションを識別するための番号。セッションとはユーザーなどの環境のこと。ユーザーが新しくログオンするごとに別のセッションが作成される |
CPU 使用率 | 現在どの程度CPUを使っているかを表す比率。例えば1 CPU/4コアのシステムで、あるプロセス(のスレッド)が1つのコアだけを全部占有し続けていると25%となる |
CPU 時間 | プロセスが開始されてから、CPU上で実行された(「実行」状態になった)延べ時間 |
メモリ―ワーキングセット | プロセスに実際に割り当てられている現在のメモリサイズ |
メモリ―コミットサイズ | プロセスに割り当てられているメモリ空間サイズ(一部がスワップアウトしていると、ワーキングセットよりも小さくなる) |
基本優先度 | プロセスの基本的な優先度 |
ハンドル | 利用しているリソースのハンドル数 |
スレッド | プロセス中のスレッド数 |
USERオブジェクト | USER.DLLオブジェクト数 |
GDIオブジェクト | GDI.DLLオブジェクト数 |
イメージパス名 | 実行ファイルのフルパス名 |
コマンドライン | プロセスパラメーター |
ユーザーアカウント制御(UAC)の仮想化 | UACによる仮想化の状態 |
説明 | プロセスの説明 |
データ実行防止 | DEP機能が有効かどうか |
プロセスの詳細画面の意味(抜粋) タスクマネージャーのプロセスタブで表示される項目のうち、プロセスやレッドに関するものの意味。 |
プロセスが最初にどのように作成されて実行を開始するか、そしてどのように終了するかのシーケンスは次の通りである。
1.実行ファイルの判定
プロセスはWin32の「CreateProcess〜()」という一連のAPIを使って起動される。このAPIが呼び出されると、Windows OSカーネルは.EXEファイルを開き、その種類を判定して、何を実行するかを決定する。一般的な.EXE形式のプログラムファイルならそのまま実行するが、そのままでは実行できない場合は、それらを実行するための補助的なプログラムを起動して処理を依頼する。以下にその例を記す。
2.プロセスの実行環境の準備
実行するプログラムファイルのイメージ(.EXEファイル)が決定できたら、それを起動するために必要なメモリ(コード、データ、ヒープ用など)の割り当てや、プロセスデータ用の構造体(前述したプロセスの詳細の表で示したようなデータを保持するための構造体)の割り当て、プログラムイメージのロード(メモリへのマッピング)などを行う。
3.スレッドの準備
プロセスはプログラムの実行単位(プロセスリソースの割り当て単位)であるが、実際にCPUコア上で実行されるのは、後述する「スレッド」である。ここでは最初に実行するスレッドの環境(スレッドコンテキスト)を作成して、実行待ち行列にスレッドを登録し、実行の開始を待つ。
1つのプロセスの中には1つ、もしくは複数のスレッドが含まれており、このスレッドが実際にCPUで実行される単位となる。同一プロセスに属するスレッドは、同じコードやデータ、ヒープ、DLLなどのメモリ空間を共有しており、各スレッドがそれらのデータなどを参照しながら、協調して動作するようになっている。
複数のスレッドは同時に並行動作させることが可能だ。これにより、アプリケーション全体がスムーズに実行されるだけではなく、CPUの持つマルチコアの機能をうまく引き出せる。
例えばワープロアプリケーションなら、ユーザーの入力を受け付けてそれを内部編集バッファーに反映したり、そのバッファーを参照して画面上に表示したり、文書を印刷したり、検索や置換をしたり、ファイルを入出力したり、といった操作は、(準備が整っていれば)同時に進めることが可能である(実際のアプリケーションではさらに細かい単位で処理を分散させている)。また大規模な計算アプリケーションなら、CPUコアの数だけスレッドを同時に実行して計算を進めれば、CPUの持つ計算能力を全て活用できる。プロセスを作成すると最初に1つ初期スレッドが作成されるが、2つ目以降のスレッドを利用するかどうかはアプリケーション次第である。
スレッドを作成すると、それに対応して「スレッドコンテキスト」が作成される。この中には、所属するプロセスの情報やスタックポインター、CPUレジスター、スケジューリング情報など、スレッドごとに必要となる情報が保存されている。
Copyright© Digital Advantage Corp. All Rights Reserved.