デバイスドライバをはじめ、デバイスにかかわるお困りごとの際はお気軽にお問い合わせください。
【 デバドラ講座14 : システムの起動 】
システムの起動(ブート処理)
Windows NTの起動処理は非常に複雑です。しかし、ブート時にロードする必要があるデバイスドライバを開発する際には、ブート処理を理解することが不可欠です。ブート処理は次の8つのステップで構成されています。
- ファームウェアの実行
- OSローダー
- カーネルの起動
- 構成マネージャの初期化
- Executiveローダー
- ローダーブロックの開放
- セッションマネージャ
- サービスコントローラ
これらのステップを1つ1つ説明していきます。
1. ファームウェアの実行
PCに電源が入れられると、まずBIOSにあるブートROMが実行されます。ブートROMはメモリをスキャンしメモリのサイズを調べ、メモリが正常に動作しているかを調べます。また、バスの検出と初期設定を行います。そして、ハードディスクからブートセクタをロードし、制御はブートセクタのコードの実行に移されます。
2. OSローダー
OSローダーはバスからハードウェアの構成を取得し、メモリにその情報を構築します。OSローダーはメモリにローダーブロックという非ページプールメモリの情報構造を生成し、検出したハードウェアの記述を参照するポインタをこの構造に設定します。次に、カーネル、HAL、ブート時に必要なデバイスドライバとファイルシステムドライバをロードします。ここではstartキーに0が設定されているドライバをロードします。
3. カーネルの起動
このステップでは、レジストリからロードを制御するための情報が読み込まれます。レジストリには、非ページプール、ページテーブルエントリなどの仮想メモリを制御するパラメータを設定します。また、頻繁に使われるレジストリの構造を保持するためのメモリのサイズも設定します。
4. 構成マネージャの初期化
このステップでは、CmInitSystemというカーネルコンポーネントによって、HKEY_LOCAL_MACHINEのHARDWAREサブキーとSYSTEMサブキーが初期化されます。この時点では、これらの2つのサブツリーにのみアクセスが可能です。続いて、レジストリAPIが有効になるので、システムサービス等のアプリケーションレベルからのレジストリに対するアクセスが可能になります。また、現在実行されているコントロールセットに対し、CurrentControlSetへのリンクも確立されます。
5. Executiveローダー
このステップでは、IoInitSystemというカーネルコンポーネントによってWindows NT Executiveの残りのコンポーネントが初期化され、ロードされます。ここで、startキーに1が設定されているドライバをロードし、初期化します。また、OSローダーによってロードされたドライバを初期化します。 ここまでステップでロードされるドライバには必ず正常に動作しなければなりません。ここでのドライバの初期化に失敗すると、ほとんどの場合ブートを継続することができません。場合によっては、OSを再インストールしなければなりません。
6. ローダーブロックの解放
このステップではMmFreeLoaderBlockというカーネルコンポーントによってメモリ上のローダーブロックが解放されます。また、カーネルの起動時に生成されたHKEY_LOCAL_MACHINE\SYSTEMの最初のコピーが破棄されます。HKEY_LOCAL_MACHINE\HARDWAREのコピーは次のステップまで残ります。
7. セッションマネージャ
このステップでは、起動時に固有のプログラムが実行されます。詳細については、ドライバ開発に関係ありません。ここで、残りのレジストリが初期化されるので、全てのレジストリエントリが使用可能になります。レジストリの書き込み要求の一部は遅延されており、このステップで全ての情報をレジストリに書き込みます。
8. サービスコントローラ
このステップではstartキーに2が設定されているドライバをロードし、初期化します。ここでロードされるドライバは初期化に失敗しても、システムの起動には深刻な影響は与えません。ただし、エラーが発生した際に警告メッセージが表示されます。設定によっては、何も表示されない場合もあります。このステップが終了すると、システムが正常に起動することが保証されるため、前回正常に起動したコントロールセットとしてHKEY_LOCAL_MACHINE\SYSTEM\Select\LastKnownGoodに設定されます。このステップでブートの起動は終了します。
ドライバがいつロードされるかは、レジストリに収められている値で決まります。HKEY_LOCAL_MACHINE\CurrentControlSet\Servicesキーにドライバの名前がついたサブキーが存在します。そのサブキーの下にドライバのロードのタイミングを示すStart値が収められています。表1にStart値とロードのタイミングを示します。
Start値 | 定義 | スタートの種類 | ロードタイミング |
---|---|---|---|
0x00 | SEVICE_BOOT_START | ブート | OSローダー |
0x01 | SEVICE_SYSTEM_START | システム | Executiveローダー |
0x02 | SEVICE_AUTO_START | 自動 | サービスコントローラ |
0x03 | SEVICE_DEMAND_START | 手動 | 要求に応じて手動で開始 |
0x04 | SEVICE_DISABLED | 無効 | ロードしない |
ブートストラップ操作自身に必要なドライバのStart値は0x00に設定されます。先または後で開始する特別な理由がないドライバのStart値は0x01に設定されます。キーボード、フロッピーディスクなど、ほとんどの標準NTドライバは、0x01に設定されています。初期化の段階で重要でないドライバのStart値は0x02に設定されています。PCの起動時にロードされるのはここまでです。Start値が0x03のドライバはユーザーの操作によって手動でロードされます。Start値が0x04に設定されているドライバはロードできません。ロードを可能にするには、Start値を変更しなければなりません。
Start値が実際どのようにレジストリに収められているか確認してみます。図1はHKEY_LOCAL_MACHINE\CurrentControlSet\Services\Beepに収められている値です。Start値には0x01が収められているので、システムの初期化のタイミングでロードされます。Start値以外にもErrorControl、Group、Tag、Typeがあります。ErrorControlは、システムがドライバの開始に失敗した際、どのように対処するかを示します。Groupは、システムスタートアップ時のドライバ起動の順番が収められています。Tagはスタートアップグループ内での起動の順番が収められています。Typeは、このエントリのタイプを示します。例えばドライバ、ファイルシステム、アプリケーション等です。
参考資料
- 「NTドライバプログラミング」
- Peter G. Viscarola、W. Anthony Mason著 久保雅俊、三浦秀朗訳 サイエンスパーク株式会社 監修
- 「Windows NTデバイスドライバプログラミング」
- アート・ベーカー著 WinProgDDK ML和訳プロジェクト訳
- 「WDMデバイスドライバプログラミング完全ガイド」上
- Edword N. Dekker, Jpseph M. Newcomer著 株式会社クイック訳