Comments
Description
Transcript
1.1 歴史的な概要
5 目次 はじめに ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・19 第 1 章 ドライバの概要 33 1.1 歴史的な概要 ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・33 1.2 Windows NT のアーキテクチャ ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・43 1.3 優先度 ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・ 44 1.4 Windows NT のシステムアーキテクチャ ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・48 1.4.1 カーネルモードとユーザーモード ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・49 1.4.2 HAL ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・ 49 1.4.3 BIOS と ARC ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・ 50 1.4.4 カーネル ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・ 50 1.4.5 Executive サービス ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・51 1.4.6 制御の移動 ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・51 1.4.7 ブート処理 ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・52 1.5 デバイスドライバの概要 ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・55 1.6 ドライバの開発のはじめに ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・60 1.7 C++の使用 ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・ 63 1.8 デバイスドライバの設計 ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・66 1.9 参考資料 ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・ 66 第 2 章 ユーザーレベルの I/O の概要 69 2.1 ユーザーレベルの I/O の基本 ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・ 69 2.1.1 同期 I/O と非同期 I/O ・ ・ ・・ ・ ・ ・ ・ ・ ・ ・ ・・ ・ ・ ・ ・ ・ ・ ・ ・・ ・ ・ ・ ・ ・ ・ ・ ・・ ・ ・ ・ ・ ・ ・ ・ ・・ ・ ・ ・ ・ ・ ・ ・ ・ ・・ ・ ・ ・ ・ ・ ・ ・ ・・ ・ ・69 2.1.2 ユーザーレベルの API ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・71 2.1.3 そのほかの I/O 操作 ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・ 81 2.2 参考資料 ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・ 82 第 3 章 デバイスドライバの設計 83 3.1 ユーザーレベルインターフェイスの設計 ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・ 83 3.1.1 デバイスの例 その 1 ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・84 6 目次 3.1.2 デバイスの例 その 2 ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・85 3.1.3 デバイスの例 その 3 ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・85 3.1.4 設計上のそのほかの検討項目 ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・ 86 3.2 Windows NT はリアルタイムシステムではない ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・ 87 3.3 アプリケーションについて ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・88 3.4 ハードウェアについて ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・89 3.4.1 実際の動作 ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・91 3.5 ドライバの設計 ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・92 3.5.1 ReadFile、WriteFile、DeviceIoControl、CancelIo の選択 ・・・・・・・・・・・・・・・・・・ 92 3.5.2 アドレスのマッピング ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・92 3.5.3 ページメモリと非ページメモリ ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・ 93 3.5.4 バッファI/O と直接 I/O ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・ 96 3.5.5 IRP の処理 ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・97 3.6 デバイスとデバイスオブジェクト ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・98 3.7 デバイスとコントローラ ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・98 3.8 アダプタオブジェクト ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・99 3.9 割り込みの処理 ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・99 3.9.1 ISR ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・ 99 3.9.2 DPC ルーチン ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・100 3.9.3 ポーリングデバイスと割り込みの頻度 ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・101 3.10 同期とシリアル化 ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・ 102 3.10.1 ドライバスレッド ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・103 3.10.2 全二重デバイス ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・ 103 3.11 バスの列挙 ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・103 3.12 電源管理 ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・ 104 3.13 ドライバのアンロード ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・104 3.14 レジストリ ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・105 3.15 イベントのログとジャーナル ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・ 105 3.16 各国語版のドライバ ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・ 108 3.17 ドライバのコーディング ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・108 3.18 ドライバのテスト ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・ 109 3.19 参考資料 ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・ 111 第 4 章 I/O ハードウェアと内部バス 113 4.1 デバイスレジスタ ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・114 4.2 メモリマップデバイスレジスタ ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・ 116 4.3 デバイスメモリ ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・117 目次 7 4.4 バス構造 ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・ 118 4.4.1 ISA バス ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・118 4.4.2 MCA バス ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・ 121 4.4.3 EISA バス ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・ 122 4.4.4 PCI バス ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・125 4.4.5 PCI ブリッジ ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・132 4.5 デバイスに関する基本的な検討事項 ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・135 4.6 まとめ ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・136 4.7 参考資料 ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・ 136 第 5 章 デバイスドライバの基礎 137 5.1 カーネルモードのドライバ ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・138 5.2 ドライバの制約 ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・138 5.3 レジストリ ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・ 139 5.4 ドライバの特性 ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・140 5.5 マルチスレッド処理とマルチプロセッサに関する検討事項 ・・・・・・・・・・・・・・・・・・・・・142 5.6 IRP ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・ 144 5.6.1 階層化ドライバと IRP ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・ 148 5.7 非同期 I/O ・ ・ ・ ・ ・ ・ ・ ・・ ・ ・ ・ ・ ・ ・ ・ ・ ・・ ・ ・ ・ ・ ・ ・ ・ ・・ ・ ・ ・ ・ ・ ・ ・ ・・ ・ ・ ・ ・ ・ ・ ・ ・・ ・ ・ ・ ・ ・ ・ ・ ・・ ・ ・ ・ ・ ・ ・ ・ ・ ・・ ・ ・ ・ ・ ・ ・ ・ ・・ ・ ・ ・ ・ ・ 148 5.8 オブジェクト指向 ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・149 5.9 参考資料 ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・ 150 第 6 章 カーネルメモリの概要 151 6.1 デバイスドライバとメモリ管理 ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・ 151 6.2 仮想アドレス空間 ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・153 6.3 物理メモリシステム ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・ 154 6.3.1 高度なキャッシュ ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・160 6.3.2 Intel ハードウェアのキャッシュの管理 ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・ 161 6.3.3 パイプライン化 ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・162 6.4 ページテーブルのキャッシュ ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・165 6.4.1 キャッシュラインと境界揃え ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・165 6.5 Windows NT のメモリ管理 ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・ 166 6.5.1 LRU 、ワーキングセット、スラッシング ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・ 168 6.5.2 非ページメモリ ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・171 6.6 デバイスドライバのメモリ管理 ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・ 172 6.6.1 ファイルキャッシュ ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・ 173 6.7 参考資料 ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・ 173 8 目次 第 7 章 ドライバのデータ構造 175 7.1 ドライバのロードと起動 ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・175 7.2 ドライバオブジェクト ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・ 180 7.2.1 ドライバのロード ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・ 181 7.2.2 ドライバのロードの順序 ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・ 182 7.2.3 ドライバの追加 ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・183 7.2.4 ドライバオブジェクトの構造 ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・ 183 7.3 デバイスオブジェクトの生成 ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・185 7.3.1 デバイスオブジェクトの構造 ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・ 186 7.4 アダプタオブジェクト ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・ 188 7.5 コントローラオブジェクト ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・188 7.6 割り込みオブジェクト ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・ 188 7.7 タイマーオブジェクト ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・ 189 7.8 DPC オブジェクト ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・ 189 7.9 ファイルオブジェクト ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・ 189 7.10 イベントオブジェクト、セマフォオブジェクト、 ミューテックスオブジェクト ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・ 191 7.11 IRP ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・ 191 7.11.1 IRP _MJ_CREATE ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・193 7.11.2 IRP _MJ_READ ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・ 193 7.11.3 IRP _MJ_WRITE ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・ 194 7.11.4 IRP _MJ_CLOSE ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・ 195 7.11.5 IRP _MJ_DEVICE _CONTROL ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・ 195 7.11.6 IRP _MJ_INTERNAL _DEVICE _CONTROL ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・196 7.11.7 IRP _MJ_SHUTDOWN ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・197 7.11.8 IRP _MJ_CLEANUP ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・197 7.11.9 IRP _MJ_FLUSH_BUFFERS ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・ 198 7.12 まとめ ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・ 198 第 8 章 デバイスドライバの構造 199 8.1 “ Hello World ”ドライバ ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・ 199 8.1.1 デバッグ情報の出力 ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・199 8.1.2 Hello.h ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・ 202 8.1.3 Hello.c ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・ 203 8.1.4 DriverEntry ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・ 203 8.1.5 HelloOpen ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・206 8.1.6 HelloClose ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・ 207 目次 9 8.1.7 HelloUnload ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・208 8.2 テストプログラム ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・209 8.3 ドライバのビルド ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・211 8.3.1 チェックビルド環境とフリービルド環境 ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・211 8.3.2 BUILD コマンド ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・ 212 8.3.3 BUILD コマンドの出力 ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・ 213 8.4 レジストリの設定 ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・214 8.4.1 Regedit と Regedt32 ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・214 8.4.2 Regini ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・215 8.5 テストプログラムとドライバの実行 ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・215 8.6 ドライバの起動 ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・215 8.6.1 テストプログラムの実行 ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・ 215 8.7 I/O Explorer ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・216 8.8 参考資料 ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・ 216 第 9 章 デバイスドライバのデバッグ 217 9.1 デバッガについて ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・217 9.1.1 IDE のデバッガ( アプリケーションレベル)・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・217 9.1.2 Bounds Checker for Windows( アプリケーションレベル)・・・・・・・・・・・・・・・・・218 9.1.3 WinDbg( カーネル)・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・218 9.1.4 SoftICE( カーネル)・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・ 218 9.1.5 kd( カーネル)・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・ 219 9.2 リテールビルドとチェックビルド ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・219 9.2.1 シンボルテーブル ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・ 220 9.2.2 シンボルテーブルのストリップ ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・220 9.3 デバッグツールの使用 ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・ 222 9.3.1 物理的な構成 ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・ 222 9.3.2 オートログオン ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・225 9.3.3 ドライバのインストール ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・ 226 9.3.4 Boot.ini の変更 ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・ 228 9.3.5 Alpha におけるパラメータの設定 ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・233 9.3.6 WinDbg の構成 ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・233 9.3.7 デバッグセッションの開始 ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・237 9.3.8 ドライバのロード ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・ 240 9.3.9 クラッシュの対処方法 ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・ 241 9.3.10 エラー後の再開 ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・ 246 9.3.11 クラッシュダンプの解析 ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・247 9.3.12 未処理の例外 ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・249 10 目次 9.4 WinDbg のコマンド ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・249 9.5 ハードウェアの使用 ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・ 252 9.5.1 エクステンダカード ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・252 9.5.2 PCI バスモニタ ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・254 9.5.3 ロジックアナライザ ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・257 9.5.4 オシロスコープ ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・258 9.5.5 インサーキットエミュレータ ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・ 259 9.6 まとめ ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・261 9.7 関連製品 ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・ 261 9.8 参考資料 ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・ 262 第 10 章 基礎編 データの転送 263 10.1 IRP_MJ_DEVICE_CONTROL と IRP_MJ_INTERNAL_DEVICE_CONTROL・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・263 10.1.1 デバイス制御のバッファ ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・264 10.1.2 要求の完了 ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・273 10.1.3 バッファI/O のデバイス制御の例 ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・273 10.1.4 宣言とインターフェイス ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・273 10.1.5 アプリケーションレベルにおける使用例 ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・276 10.2 IRP_MJ_READ と IRP_MJ_WRITE ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・280 10.2.1 読み取りと書き込みのバッファ ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・ 280 10.2.2 要求の完了 ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・283 10.2.3 バッファI/O の IRP _MJ_READ と IRP _MJ_WRITE の例 ・・・・・・・・・・・・・・・・・・・ 284 10.2.4 直接 I/O の IRP _MJ_READ と IRP _MJ_WRITE の例 ・・・・・・・・・・・・・・・・・・・・・・・・286 10.3 まとめ ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・ 288 第 11 章 基礎編 同期 289 11.1 スピンロック ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・289 11.1.1 KeInitializeSpinLock ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・291 11.1.2 KeAcquireSpinLock ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・291 11.1.3 KeReleaseSpinLock ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・292 11.1.4 KeAcquireSpinLockAtDpcLevel ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・292 11.1.5 KeReleaseSpinLockFromDpcLevel ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・292 11.2 ミューテックスと高速ミューテックス ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・293 11.2.1 高速ミューテックスの関数 ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・ 294 11.2.2 ミューテックスの関数 ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・295 11.3 セマフォ ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・ 295 11.3.1 セマフォの関数 ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・ 296 目次 11 11.4 Executive リソース ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・ 298 11.4.1 Executive リソースの関数 ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・299 11.5 待機関数 ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・ 303 11.6 SynchCritSection ルーチン ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・305 11.6.1 デバイスの一貫性( KeSynchronizeExecution)・・・・・・・・・・・・・・・・・・・・・・・・・・・・ 306 11.7 キャンセルスピンロック ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・307 11.8 まとめ ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・ 307 11.9 参考資料 ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・ 308 第 12 章 実践編 メモリ管理 309 12.1 メモリの割り当てと管理 ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・310 12.1.1 カーネルメモリの基本的な割り当て ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・310 12.1.2 ルックアサイドリスト ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・314 12.1.3 ゾーンバッファ ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・ 316 12.2 デバイスメモリと I/O 空間のマッピング ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・ 316 12.2.1 デバイスメモリの管理 ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・317 12.3 ユーザーメモリ ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・319 12.3.1 ユーザーメモリの管理 ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・320 12.4 まとめ ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・ 323 第 13 章 実践編 ハードウェア 325 13.1 ポートのアクセス ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・ 326 13.1.1 ポートのマッピング ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・ 326 13.1.2 ポートの読み取りと書き込み ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・327 13.2 デバイスメモリのアクセス ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・329 13.2.1 デバイスメモリの読み取りと書き込み ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・ 330 13.3 ハードウェアの喜び ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・ 335 13.4 まとめ ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・ 337 第 14 章 実践編 割り込みとドライバ 339 14.1 下位ドライバの役割 ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・ 339 14.2 割り込み ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・ 340 14.3 割り込みについて ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・ 340 14.3.1 割り込みレベル ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・ 341 14.3.2 ISR の同期( スピンロック)・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・ 342 14.3.3 ISR のレベルとデバイスの優先度 ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・343 14.4 ISR の概要 ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・ 344 12 目次 14.4.1 ISR のプロトタイプ ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・ 344 14.4.2 ISR の要件 ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・345 14.4.3 ISR の登録 ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・346 14.4.4 割り込みの処理 ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・ 346 14.4.5 DPC の概要 ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・348 14.4.6 ISR の DPC とカスタム DPC ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・349 14.4.7 複数の DPC ルーチン ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・ 350 14.4.8 DpcForIsr ルーチン ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・350 14.4.9 カスタム DPC ルーチン ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・ 352 14.5 ISR の作成 ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・ 353 14.5.1 ISR の例 ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・ 354 14.5.2 ISR と割り込みの共有 ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・355 14.5.3 DPC の例 ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・356 14.5.4 ISR とアンロードルーチン ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・ 358 14.6 SynchCritSection ルーチン ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・358 14.6.1 リソースの割り当てのインターロック ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・ 361 14.7 まとめ ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・ 361 第 15 章 実践編 タイマー 363 15.1 ハードウェアタイマー ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・363 15.2 時間の遅延 ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・364 15.2.1 パフォーマンスの測定 ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・364 15.2.2 実行の遅延 ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・365 15.2.3 タイムアウト ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・366 15.2.4 IoTimer ルーチン ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・367 15.2.5 カスタムタイマールーチン ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・ 370 15.2.6 カスタムタイマーオブジェクトの待機 ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・ 370 15.2.7 カスタムタイマーオブジェクトのポーリング ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・370 15.2.8 CustomTimerDpc ルーチン ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・371 15.2.9 通知タイマーと同期タイマー ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・371 15.2.10 カスタムタイマーの関数 ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・ 371 15.2.11 IoTimer ルーチンの設定の例 ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・ 374 15.3 時刻関数 ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・ 375 15.3.1 時刻の読み取り ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・ 376 15.3.2 時刻の変換 ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・376 15.4 まとめ ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・ 377 目次 第 16 章 実践編 ドライバの初期化 13 379 16.1 ドライバの初期化 ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・ 379 16.2 ドライバの初期化の例 ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・380 16.2.1 ISR のセットアップ ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・ 384 16.2.2 初期化に使われる関数 ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・386 16.2.3 アンロードルーチン ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・ 389 16.3 まとめ ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・ 390 第 17 章 実践編 DMA 391 17.1 ハードウェアレベルの DMA の動作 ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・391 17.2 DMA の操作 ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・392 17.3 DMA の使用 ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・392 17.3.1 スキャッタ/ギャザ ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・394 17.4 DMA アダプタを表すアダプタオブジェクト ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・ 397 17.4.1 アダプタ制御ルーチン ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・399 17.5 DMA 処理の概要 ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・400 17.5.1 DriverEntry ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・400 17.5.2 ディスパッチルーチン ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・400 17.5.3 StartIo ルーチン ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・401 17.5.4 ISR ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・402 17.5.5 DPC ルーチン ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・ 403 17.5.6 最適化と単純化 ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・ 403 17.5.7 キャッシュの一貫性 ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・403 17.5.8 DMA チャネルの割り当て ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・404 17.6 コントローラオブジェクト ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・406 17.6.1 複数の同期オブジェクトとデッドロック ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・406 17.6.2 コントローラオブジェクトの生成と管理 ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・408 17.7 まとめ ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・ 409 第 18 章 実践編 そのほか 411 18.1 アンロードルーチン ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・ 411 18.2 ドライバのパラメータとレジストリ ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・412 18.2.1 レジストリの読み取り ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・414 18.2.2 レジストリの値の使用 ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・416 18.2.3 ドライバオブジェクトの初期化 ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・ 417 18.2.4 アンロードルーチン ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・ 419 18.3 まとめ ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・ 420 14 目次 第 19 章 カーネルおよびデバイスのメモリと ユーザー空間のマッピング 421 19.1 非ページプールからユーザー空間へのマッピング ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・421 19.2 MapMem ドライバの概要 ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・ 422 19.2.1 レジストリの値 ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・ 423 19.2.2 レジストリの読み取り ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・423 19.2.3 レジストリの値の使用 ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・424 19.2.4 ドライバオブジェクトの初期化 ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・ 425 19.2.5 IRP _MJ_CREATE ハンドラ ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・427 19.2.6 IRP _MJ_CLOSE ハンドラ ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・ 428 19.2.7 IRP _MJ_DEVICE _CONTROL ハンドラ ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・ 429 19.2.8 アンロードルーチン ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・ 434 19.2.9 mapSystemLogicalMemory ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・ 434 19.3 デバイスメモリのマッピング ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・ 441 19.4 まとめ ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・ 441 第 20 章 I/O ハードウェアと ISA バス 443 20.1 ISA バスの問題点 ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・ 443 20.2 ISA バスの歴史 ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・444 20.3 ISA アーキテクチャの概要 ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・445 20.3.1 ISA バスの最大の問題 ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・447 20.4 ISA の割り込みの構造 ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・449 20.4.1 ISA のプラグアンドプレイ ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・ 450 20.4.2 リソースの要求 ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・ 451 20.5 ISA の DMA ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・ 453 20.6 まとめ ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・ 454 20.7 参考資料 ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・ 454 第 21 章 I/O ハードウェアと PCI バス 455 21.1 PCI バスのハードウェア ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・455 21.1.1 PCI のトランザクション ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・ 456 21.1.2 ノースブリッジ ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・ 458 21.2 Windows NT における PCI バスのサポート ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・459 21.2.1 PCI デバイスの列挙 ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・ 460 21.2.2 PCI 構成空間 ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・ 460 21.2.3 HalGetBusData の詳細 ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・ 468 21.2.4 リソースの割り当て ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・ 469 目次 15 21.2.5 HalAssignSlotResources の使用 ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・ 470 21.2.6 リソースの要求 ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・ 475 21.2.7 IoAssignResources の使用 ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・477 21.2.8 割り当てのオーバーライド ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・ 479 21.2.9 メモリのマッピング ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・ 479 21.2.10 PCI Explorer ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・ 481 21.2.11 PCISCAN ドライバ ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・483 21.2.12 PCI Explorer のソースコード ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・490 21.3 まとめ ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・ 493 21.4 参考資料 ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・ 494 第 22 章 ドライバのシリアル化 495 22.1 シリアル化について ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・ 495 22.2 StartIo による基本的なシリアル化 ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・ 496 22.3 ドライバ管理キュー ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・ 502 22.3.1 キュー管理関数 ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・ 502 22.3.2 デバイスキュー ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・ 506 22.4 StartIo ルーチンに代わる処理 ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・509 22.5 マルチキューデバイス ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・510 22.6 共有デバイス ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・518 22.7 I/O 要求のキャンセル ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・ 519 22.7.1 キャンセルと階層化ドライバ ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・520 22.7.2 キャンセルルーチン ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・ 521 22.7.3 キャンセルルーチンとキャンセルスピンロック ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・521 22.7.4 StartIo によって管理される IRP のキャンセル ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・522 22.7.5 デバイスキューによって管理される IRP のキャンセル ・・・・・・・・・・・・・・・・・・・・・・・・523 22.8 まとめ ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・ 524 索 引 ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・525 33 第1章 ドライバの概要 デバイスドライバという用語は、オペレーティングシステムの歴史の中でさまざまな意 味を持ち、デバイスドライバの使用目的も多岐にわたる。Windows NT の場合、デバイ スドライバは複数の非常に特別な意味を持つ。なぜ、複数なのだろうか。本章で説明する が、Windows NT/2000 のデバイスドライバには数多くの種類があり、正確な意味は文脈 *1 によって異なる。 しかし、まず、一般にデバイスドライバによって解決される問題と、 デバイスドライバの重要性について検討しよう。 1.1 歴史的な概要 古き悪しきメインフレーム時代には、パンチカードの読み取りを行うためにカード読み 取り命令を発行していた( 図 1-1 を参照) 。アプリケーションは周辺装置に直接接続され、 直接的かつ物理的に組み込まれた命令によって装置を操作する。カード読み取り命令を発 行するときには、データの出力先のアドレスを指定できる場合もあるが、データがメモリ 内の特定の組み込みアドレスに送られることもあった。万事はうまく進んでいたが、数億 円ものメインフレームにカードの読み取りを実行させるのは良い考えではないという意見 が出された。そこで、カードを読み取って磁気テープに書き込むより安価なシステムが使 われるようになった。メインフレーム上のアプリケーションがこの磁気テープを読み取る。 このほうがはるかに処理が速い。ただし、いくつかささいな問題はあった。まず、メイン フレームのプログラムを書き直して、カード読み取り命令をテープ読み取り命令に置き換 える必要があった。次に、テープはよく止まり、読み取りが成功しないこともある。この 場合、テープを巻き戻して操作を再試行しなければならない。この問題のために、プログ *1 本書では、デバイスドライバの説明をカーネルモードのデバイスドライバに限定する。カーネルモード のデバイスドライバに共通する話題を取り上げ、特定のドライバに関して詳細に説明する。Windows NT/2000 にはそのほかにもデバイスドライバと呼ばれるコンポーネント( TAPI ドライバ、仮想 DOS ドライバなど)が存在するが、ユーザーモードで動作するものであるため、本書では取り上げない。 34 第1章 ドライバの概要 ラムのコードに実際のテープ読み取り命令を入れることを避け、代わりにアプリケーショ ンにリンクされたサブルーチンライブラリを呼び出すようになる( 図 1-2 を参照)。オペ レーティングシステムを使えばよいと思われるが、当時のオペレーティングシステムとい えば、メモリをクリアしてアプリケーションをロードし、それを実行しても、次のジョブ を開始するにはまたメモリをクリアし、新しい実行可能イメージをロードしなければなら なかったのだから。 アプリケーションプログラム テープ カード ディスク 図 1-1 アプリケーションがデバイスを直接操作する場合 アプリケーションプログラム サブルーチンライブラリ テープ カード ディスク 図 1-2 アプリケーションがサブルーチンライブラリを使う場合 しだいに、常に同じサブルーチンが使われていることが明らかになり、整理と統合が必 要になる。整理と統合の必要性を後押しする理由はほかにもあった。あるサイト内のテー プドライバをモデル T からモデル A にアップグレードする場合、すべてのアプリケーショ ンを新しいサブルーチンライブラリに再リンクしなければならない。ただし、ここで再リ ンクする代わりに、サブルーチンライブラリをコンピュータにあらかじめロードしておき、 アプリケーションをロードする( 図 1-3 を参照)。アプリケーションは、実際にはすでに ロードされているテープ読み取り用のサブルーチンを呼び出す。このとき、テープ読み取 り用のサブルーチンの呼び出しが保存されているメモリ上の特定の位置を呼び出すなどの プロトコルを使う。この方法であれば、呼び出しの位置は、実際のサブルーチンのアドレ スと無関係になる(スタックへの影響を心配する必要はない。スタックは 1 つもない) 。こ のシステムはプロトタイプのオペレーティングシステム、つまり現在のオペレーティング システムの祖先である。現在のシステムを深くまで掘り進めると、当時の骨格の名残りが 見られる。 1.1 歴史的な概要 アプリケーションプログラム サブルーチンプログラム テープ カード 35 何度も変更され、 ロードされる メモリに残る ディスク 図 1-3 オペレーティングシステムの原型となった固定のサブルーチンライブラリ 時間の経過とともに、これらのサブルーチンライブラリはより洗練されていく。たとえ ば、テープ読み取りは入力読み取りになり、読み取った入力を物理的なパンチカード、磁 気テープ、最新の回転式磁気記憶域デバイスなどに対して動的に再割り当てすることがで きるようになった。1960 年代中期に IBM の OS/360 が登場する頃には、入力を動的に再 割り当てする技術は芸術の域に達するほど高められていた。OS/360 はまだ設計もされて いないデバイスを処理する特権付きのコードセグメントを動的にロードすることが可能で、 オペレーティングシステム全体を再コンパイルする必要がなかった。つまり、ユーザーは、 このオペレーティングシステムが最初に作成されたときには存在しなかったデバイスに入 力または出力を割り当てることができたのである。また、デバイスドライバとアプリケー ションのインターフェイスは抽象的なものであった。一度に 1 つしか使えない単純なチャ ネルを持つローエンドコンピュータでは、同時に複数の入出力( I/O )操作が可能である高 度なコントローラを備えたハイエンドコンピュータとはまったく異なるデバイスドライバ が使われる。アプリケーションは同じファミリのすべてのコンピュータで同じように動作 した(まあ、まったく同じというわけではない。システム生成( SYSGEN )タスクは個別の コンポーネントからオペレーティングシステムを組み立てた。非常に複雑であるため、失 敗することもあったが、オペレーティングシステムアーキテクチャの主要なマイルストー ンとなるだけの働きはした) 。 ほかのオペレーティングシステムは、あまり幸運ではなかった。たとえば、Digital の TOPS-10 や TOPS-20 にデバイスドライバを追加するためには、デバイスドライバモ ジュールをアセンブリ言語でコーディングして、オペレーティングシステム全体を再リン クし、再起動しなければならない。UNIX ではドライバを C 言語でコーディングするが、 最近のバージョンになるまではシステムとリンクして完全なシステムイメージを形成する 必要があった。 Digital の RSX-11 オペレーティングシステム( PDP-11 用)は、ロード可能なデバイス ドライバという概念を備えていた。この概念は VMS オペレーティングシステム( Digital VAX 用)に受け継がれた。 36 第1章 ドライバの概要 その後の UNIX*2 では、構成可能なデバイスドライバという概念が広められた。あいに く、ほとんどの UNIX と同様に、それほど作り込まれていなかったため、うまく機能しな かった。構成スクリプトは独特の構文を持ち、カンマの位置が異なる、空白行が入れられ ている、最後の行末に改行がないなどの場合にはシステムがクラッシュした。また、コメ ントの規則がなかったり、無視された( そのため、コメント行が実際にコメントになって *3 いるかどうかなど、ドライバ間で一貫していなかった) 。 デバイスドライバ内のテーブルを手作業で編集する処理( 物理ディスクを論理パーティ ションに分けるなど)は、実際にはシステム管理機能であった。システム管理者( 現場の システムプログラマ)は目的のパーティションサイズをドライバのソースコードに組み込 み、物理的に同じ種類のディスクはすべて同じパーティション方式を使うことになる。し かし、実行方法がまずいわりには、これはこれで優れた考え方であった。UNIX のデバイ スドライバでは、カーネルのソースコード全体を丹念に調べられることを前提としていた。 AT&T が UNIX の商用ライセンスを 10 万ドルに値上げしたことにより、UNIX のデバイ スドライバの開発に対する興味は薄れていった。 UNIX では移植性という概念も提唱された。ほとんど均質な IBM 360 シリーズとは異 なり、UNIX は PDP-11 、Digital VAX 、IBM RISC 6000( AIX 搭載)、Motorola 680x0 、 National Semiconductor、Intel 80x86 など、多様なプラットフォームで動作した。デバイ スドライバは実際には移植可能ではなく、完全に書き換えなければならないことが多かっ たが、アプリケーションとデバイスドライバのインターフェイスは本質的に変わらなかっ た。このため、アプリケーションを新しいコンピュータ用に再コンパイルすれば、別のコ ンピュータで使われていたデバイスに問題なくアクセスすることができた。UNIX に対す る関心を集めたのは、移植性には問題があるが、まったく新しいオペレーティングシステ ムを作成するより、UNIX を新しいアーキテクチャに移植するほうが安上がりだという事 実である( 何年もの間、カーネル部分は、生成済みのアセンブリコードに対して sed のス クリプトを実行し、コードの必要な部分を修正することによって生成されていた。このた め、カーネルを生成する作業では、コンパイラによるレジスタの割り当てなどの非常識的 な問題に敏感になった) 。 最初のマイクロプロセッサの開発とともに、最初のマイクロプロセッサオペレーティン グシステムである CP/M が開発された。CP/M は、BIOS( Basic Input/Output System ) という新しい概念を導入した。BIOS には制約も多いが、重要性は強調しても強調しすぎ ることはない。BIOS は、システムデバイスを制御するコードで、そのサイズはわずかであ る。CP/M では、BIOS を介してシステムデバイスにアクセスするため、フロッピーディ スクやディスプレイの実装方法を意識する必要がなく、常に同じ BIOS のルーチンを呼び 出すだけで済む。起動用フロッピーディスクには、少数の専用ブロックに BIOS が配置さ *2 UNIX の初期バージョン( BSD 4.2 まで)は、ディスクのサイズなどの単純なパラメータでも、変更 を加えるにはドライバのソースコードを修正する必要があった。 *3 これは事実である。著者は実際にその現場にいたのだ。デバイスを指定する行に似ているコメント行 は、行頭にコメントを示す記号が付けられていてもデバイスを指定する行として解釈された。このよ うな問題のデバッグに数時間かかることさえある。 1.1 歴史的な概要 37 れた。BIOS を新しいコンピュータで動かすために、BIOS を CP/M の起動ディスクに書 き込むプロシージャもあった。 IBM(および Microsoft )が初めてパーソナルコンピュータ( PC )を開発したとき、BIOS は読み取り専用メモリ( ROM )に移された。パーソナルコンピュータ業界はプログラムと しての BIOS の機能が追いつかない勢いで急成長したが、BIOS は依然としてパーソナル コンピュータのオペレーティングシステムの起動とデバイスドライバのロードに必要なサ ポートを提供している。 IBM と Microsoft のコンビは MS-DOS を生んだ。MS-DOS は、おそらく現時点で歴 史上もっとも重要なオペレーティングシステムである。これは、新しい概念が取り入れら れたからでもなく( 取り入れられていなかった) 、洗練されていたからでもなく( 洗練され ていなかった)、移植性があったからでもなく( 8088 のアセンブリでコーディングされてい た)、信頼性があったからでもなく( 苦笑)、安全だからでもない( 爆笑) 。単に世界でもっ とも広く普及したオペレーティングシステムだからである。現在(そしてあと数年は)、世 界中で動いている MS-DOS の本数は、この分野の歴史とオペレーティングシステムの全 歴史に登場するほかのすべてのオペレーティングシステムより多い。実際、これでも控え めなくらいだ。おそらく、本書を読んでいる今もフォーチュン 500 社のそれぞれで動いて いる MS-DOS の本数は、オペレーティングシステムの歴史上のほかのどのオペレーティ ングシステムの本数より多いはずである。 MS-DOS に不名誉なあだ名を付けるのは、オペレーティングシステムの愛好家( 特に UNIX ユーザー)の間ではファッショナブルであるとみなされている。もっともよく知られ ており、活字にしても支障が少ないのは、 “ Messy-DOS ”というあだ名だ。オペレーティ ングシステムとしてはかなりの力不足であるうえ( 実際、図 1-3 に示すように、デバイス 管理を行うためにあらかじめロードされているサブルーチンのセットにすぎない)、UNIX 派からは一様に軽蔑されているにもかかわらず、歴史上ほかのオペレーティングシステム には達成できなかった何かを成し遂げた。MS-DOS により、コンピュータを使うはずの なかった数百万のユーザーがコンピュータを使えるようになった。Microsoft が 1 週間に 出荷する MS-DOS の本数は、優良ベンダーが製品の耐用年数の全期間で販売する専用オ ペレーティングシステムの本数より多い。このような勢いを無視すると、落ちこぼれるこ とになる。事実、多くの企業がそうなった。 MS-DOS は、ロード可能なデバイスドライバという実に興味深い特徴を備えている。 これは新しい概念ですらない( OS/360 、RSX-11 、VMS にはすでにこの概念が取り入れ られていたし、そのほかにもこの機能を備えたオペレーティングシステムがいくつかあっ た)。しかし、MS-DOS は、このドライバを数百万のユーザーから見えるようにしたの である。システムプログラマ、サイト管理者、技術指導者以外でも、デバイスドライバを インストールすることができる。Config.sys に 1 行挿入するだけで、デバイスドライバが ロードされる。本当の MS-DOS のデバイスドライバを開発することはほとんどない。実 際のデバイスドライバと対話するプロトコルは複雑かつ非効率的で、ドキュメントもあま りない。代わりに、Config.sys の DEVICE=の行を使ってデバイスに対してなんらかのアド ホックなインターフェイスをサポートするプログラムをロードしたり、自動的に開始して 38 第1章 ドライバの概要 終了する Autoexec.bat からプログラムを実行して通常のプログラムのアンロードを無視 することにより、ほとんどのデバイスドライバをロードすることができる。Autoexec.bat によってロードされるプログラムは常駐終了型( TSR )プログラムと呼ばれ、コード(多く 。TSR は MS-DOS の重要な の場合はデバイスドライバ)をメモリに残す(図 1-4 を参照) 機能の 1 つであるが、ユーザーとシステム管理者の悪夢にもなった。TSR の制御に関す るドキュメントおよび確立されたポリシーがなかったからだ。このため、2 つ以上の TSR が同じリソースを同じ方法で奪い合うことがあった。通常は、この結果としてシステムが クラッシュする。 アプリケーションプログラム モデム ロード可能なデバイスドライバまたはTSR ロード可能なデバイスドライバまたはTSR MS-DOSの中核のコード 何度も変更され、 ロードされる Config.sysや Autoexec.bat、 またはユーザーの特定の 操作によりロードされる ディスクからブート される固定のコード 組み込みのデバイスドライバ キーボード ディスク 図 1-4 MS-DOS のアーキテクチャ(理想) MS-DOS のドライバのもう 1 つの大きな問題は、それぞれがアドホックなインターフェ イスを使っていたことだ。このインターフェイスは標準であるはずだったが、実際にはそ うではないことが多かった。数多くのベンダーに支持される標準となったデバイスドライ バは、マウス用などのごく少数に限られた。一般に、デバイスの独立性は 1 つのベンダー の製品ラインに限定され、それも幸運に恵まれた場合に限られた。マウス用のドライバ 以上に重要なドライバの 1 つは、MS-DOS の晩年に登場した。SCSI デバイス用の ASPI ( Advanced SCSI Programming Interface )標準である。SCSI デバイスのトップベンダー である Adaptec によって広められた ASPI 標準はデバイスに依存しない SCSI インター フェイスを提供し、すべてのアプリケーションやファイルシステムは 1 つの統一されたプ ロトコルですべての SCSI デバイスと対話することができた。ASPI はオープンな標準で あり、多くの SCSI ベンダーによって採用された( Windows NT の ASPI については、第 25 章「 Windows NT の専用ドライバ」で説明する) 。 1.1 歴史的な概要 39 ベンダーに依存しないサブルーチンライブラリがいくつか普及した。特に、シリアル I/O のライブラリは好評で、使用中の特定のシリアル I/O チップ*4 に依存しないプログラ ミングを可能にしたり、標準的ではないマルチポートのシリアルカードを数多く一律にサ ポートした。多くは、サブルーチンをアプリケーションにリンクする初期のモデル(図 1-2 と同様であったが、TSR ドライバを使うものもあり、新しいデバイスの登場に伴って拡張 することができた。 ただし、MS-DOS の実装の真価は、オペレーティングシステムを再リンクすることな くオペレーティングシステムの機能を動的に拡張できることであった。その後のオペレー ティングシステム( Apple Macintosh など)も同様の機能を備えている。主流の UNIX が この概念に追いついたのはわずか数年前のことである。 しかし、開発者は TSR でオペレーティングシステムを拡張する機能を利用したのだろう か。多くのアプリケーション、特に固有のアドオンボードとともに配布されたアプリケー ションは、専用のデバイスドライバに対しても TSR を利用しなかった。代わりに、事実上 はカード読み取り命令に相当するものに手を伸ばしただけである。これが機能したのは、 MS-DOS ベースのシステムには保護機能がなかったためだ。任意のプログラムが自由に 命令を実行することができた。アプリケーションの多くは加工していない金属にプログラ ミングされているようなもので、特定のデバイスの処理については MS-DOS の存在その ものを無視した。結局、図 1-1 の形式により近くなったのである。 次に登場したのは Windows だ。Windows 3.1 は、16 ビットの Windows シリーズでお そらくもっとも重要である。セグメント化され、保護された 32 ビットのアドレス空間で 動作するからだ( Windows 3.0 でも 8088 をサポートしているが、メモリを保護していな い)。これにより、割り込みベクタを変更するアプリケーションの開発が難しくなった。 Windows 3.1 では、INT 21h の機能 25 または機能 35( または DPMI の機能)による割り 込みのマッピングが必要であった。もう、アプリケーションやドライバがハードウェアの 割り込みベクタを直接変更する(未加工の金属に書き込む)ことはできない。Windows 3.1 には Windows 3.0 によって使われたデバイスドライバ( .drv ドライバ)が残されたが、仮 想デバイスドライバ( VxD )*5 と呼ばれる新しい種類のデバイスドライバも導入された。 VxD は、当初は使用が限定されていたが、Windows 3.1 のデバイスインターフェイスを作 成するための一般的な手段になった。また、デバイスの種類によっては、純粋なインター フェイスに準拠したデバイスドライバ以外の手段でアクセスすることはできなかった。 *4 PC のマザーボードに使われるシリアル I/O チップはすべて、主要機能について互換性を備えている が、その後のチップは FIFO を提供した。ライブラリは、搭載されているチップを調べてシリアル チップに対応する最適な動作パラメータを使う。 *5 Windows 3.1 は、複数レベルのオペレーティングシステムとして実装された。仮想マシンマネージャ ( VMM )は最下位レベルで動作して仮想 8088 環境を管理した。Windows のサブシステムは、最初の 仮想 8088 環境で動作した。同時実行の DOS プロセスは、ほかの仮想 8088 の仮想環境で動作した。 ハードウェアの割り込みは、まず、下位層の VMM によって処理され、この処理が下位層のレベルで 完了しない場合には割り込みはそれぞれの仮想 8088 環境に渡された。VxD は、下位層の VMM の コンポーネントとして動作するデバイスドライバである。.drv ドライバは、Windows システムのコ ンポーネントとして動作する。drv ドライバの割り込みの遅延は、.drv ドライバの割り込みの遅延よ りかなり長かった。 40 第1章 ドライバの概要 Windows 3.1 の後には、Windows 95 および Windows 98 が続いた。Windows 95 と Windows 98 は、大量の 16 ビットのサポートコードから構成されるコードベースを使って フラットな 32 ビットのアドレス空間、プリエンプティブなマルチタスク処理、32 ビット 指向の API などの機能を追加している。この API は、32 ビットの Windows NT の API ( 参照 API )のサブセットということになっている。参照 API との関係は実際にはさらに 複雑であるが、デバイスドライバの開発に絶対に必要不可欠であるというほどではないた め、本書では説明しない。Windows 95 と Windows 98 は、.drv ドライバと VxD ドライ バの概念をデバイスドライバの堅牢なベースとして使い続けている。 最後に、Windows NT に到達する。Windows NT は、現代のほかのオペレーティングシ ステムには見られない完成度を備えている( ただし、例外として OS/2 と最近の UNIX も 完成度が高い) 。これは、設計者のリーダーである Dave Cutler に負う部分が多い。Cutler は、同様にきわめて完成度の高い Digital の VMS オペレーティングシステムの設計者の リーダーでもあった。Windows NT の実装を担当した開発者の多くは、VMS による開発 経験があった。Windows NT の歴史については、Showstopper!という書籍がお勧めだ(「参 考資料」を参照) 。 Windows NT では、プログラムは未加工の金属に書き込みを実行することはできない。 Windows NT の設計者は、C2 セキュリティを確保するため、このような規則を設けた。 C2 セキュリティの要件の 1 つに、アプリケーションからデバイスレジスタへの書き込み の禁止がある。したがって、デバイスドライバがないハードウェアを利用するためには、 最初にデバイスドライバを作成しなければそのハードウェアとやり取りできない。 Windows NT は、デバイスドライバは動的にロード可能であるという伝統に従ってい る。デバイスは、システムの起動時にロードされたり、アプリケーションで必要になると きに初めてロードされる。同様に、適切にコーディングすることにより、アンロードも可 能だ。エンドユーザーにとって、デバイスドライバのアンロードが可能であるということ は、シャットダウンせずに新しいバーションのデバイスドライバをインストールできるこ とを意味する。デバイスドライバは、理想的なことに、新しいデバイスドライバとのホッ トスワップが可能である( 実際には、デバイスドライバを使うアプリケーションがデバイ スドライバをなかなか解放しないこともあるため、常に機能するとは限らない) 。 Windows NT では、デバイスドライバはすべて特定のプロトコルに従う。実際、問題 になるのはデバイスとドライバの通信を可能にすることではなく、ドライバとシステムの ほかの部分との通信を正しく実行することである。プロトコルの要件は非常に具体的かつ 厳密である。要件に従わなければ、動作が不安定になったり、I/O の要求が正常に完了し ないだけではなく、一般的にはオペレーティングシステムがクラッシュして悪名高き「死 のブルー画面」になる。 友人のパイロットによると、計器飛行規則( IFR )に従っての飛行を学ぶのは、初心者に は外部の参照地点を見ないで飛ぶという難題に思われる。つまり、コックピットの計器だ けを使って正しい航路を維持しなければならないのだ。しかし、IFR の飛行の本当の難し さは、プロトコルを学ぶことである。IFR 航行の管制センターとのやり取り、進入図の読 み方、空港の条件が悪いときに着陸を取りやめるタイミングとその方法などだ(たとえば、 1.1 歴史的な概要 41 左側に山がある場合には上昇コースを左にとるのは非常にまずい考えである) 。Windows NT のデバイスドライバの開発は、多くの点で IFR による飛行に似ている。ドライバとデ バイスの対話が可能であるだけでは不十分で、すべてのプロトコルに従わなければならな い。さもなければ、ドライバは山腹に衝突することになる。 Windows NT の開発者は、定型的な作業の多くはすべてのデバイスに共通であること を認識している。たとえば、SCSI の最下位レベルのコマンドで SCSI のテープドライブを 扱うコードの大部分は、SCSI のディスクや CD-ROM を処理するコードと同じである。1 台のコンピュータに複数の SCSI コントローラ( 異なるベンダーの SCSI コントローラ)が 接続されている場合、唯一の違いは SCSI コマンドをカードに送る処理の最下位レベルの 詳細だけである。したがって、Windows NT は階層状のデバイス構造を持つ(図 1-5 を参 照) 。特定の層を実装した後は、それを下位の正しい層に接続するだけで済む。SCSI ディ スクのコントローラは、SCSI のレベルだけで作成できる。SCSI コマンドをドライブに送 るために、どのバイトをどのレジスタに書き込むかという詳細はそれぞれの SCSI カード で個別に処理可能である。 これは非常に重要な機能であるため、図 1-5 の例で詳しく説明しよう。図 1-5 の最上位 には 2 つのクラスドライバがあり、それぞれ CD-ROM と磁気ディスクのファイルシステ ム用である。これらのドライバにとっては、媒体の編成方法(ディレクトリを格納したり、 データを取り出す方法など)が重要な意味を持つ。たとえば、CD-ROM のファイルシス テムのドライバは、ISO-9660 の CD-ROM の構造を理解しており、FAT ファイルシステ ムのドライバは FAT などの特定のファイルシステムの編成方法を理解している。 CD-ROM のドライバがファイルを探す場合を考えてみよう。ドライバは、CD-ROM の ディレクトリを読み取る際に必要な作業を抽象的に理解している。しかし、実際の作業方 法は、読み取りの対象が SCSI または IDE のどちらの CD-ROM かによって異なる。ドラ イバは呼び出さなければならないポートドライバを認識するだけで済む。SCSI ポートド ライバはデバイスに対して SCSI コマンドを発行する方法を理解しており、IDE ポートド ライバはデバイスに対して IDE コマンドを発行する方法を理解している。しかし、どちら もコマンドを特定のデバイスに実際に渡す方法を認識していない。このため、ミニポート ドライバがベンダーまたは Microsoft から提供されている。ミニポートドライバは、SCSI コマンドまたは IDE コマンドを受け取り、コントローラカード上の実際のデバイスレジ スタにアクセスしてコマンドをデバイスに伝える方法を認識している。 図 1-5 では、SCSI のチェーンの先にフラットベッドスキャナが接続されているが、フ *6 ラットベッドスキャナ用のクラスドライバが定義されていなければアクセスできない。 階層化ドライバは、Windows NT 4.0 のデバイスドライバのプログラミングにおいては 非常に高度な問題であるが、Windows 2000 に移行すれば、階層構造はドライバの構造と して無視できないごく基本的なものになる。また、単純でモノリシックな Windows NT *6 厳密には、この記述は正しくない。SCSI のパススルーモードを使うと、アプリケーションは SCSI デバイスを直接制御できる。パススルーモードを使ってもすべてのデバイスにアクセスできるわけで はなく、アプリケーションのスケジュールの遅延によりデバイスが誤動作することもあるため、正確 なタイミングを必要とするデバイスではまったく動作しないこともある。 42 第1章 ドライバの概要 FAT ファイルシステム ドライバ NTFS ファイルシステム ドライバ CD-ROM クラスドライバ SCSI クラスドライバ AdaptecのSCSI ミニポートドライバ ほかのSCSI ミニポートドライバ ATAPIの ミニポートドライバ ATDISK ドライバ Adaptecの SCSIカード ほかの SCSIカード マザーボードの IDEチップ IDEの PCIカード SCSIディスク SCSIディスク IDEディスク IDEディスク IDEディスク SCSIディスク 図 1-5 ドライバの階層構造 4.0 のドライバは Windows 2000 でも動作するが、プラグアンドプレイや電源管理など、 Windows 2000 の優れた機能を利用することはできない。したがって、本書で説明する技 術の大部分は Windows 2000 にそのまま適用されるが、Windows 2000 の拡張機能を活用 するためには、使用方法にいくつかの制限と制約が加えられる。Windows NT のコンポー ネントと対話するためのプロトコルも多少異なる。このような問題の詳細については、第 28 章「 Windows 2000 の概要」で説明する。 Windows NT を採用するうえで重大な意味を持つ問題の 1 つは、Windows NT のデバ イスドライバのモデルは Windows 95 のモデルと完全かつ相互に互換性を持たないという ことだ。Windows NT では、デバイスおよびオペレーティングシステムのほかの部分と 通信する際に複雑なプロトコルが使われる。Windows 95 では、オペレーティングシステ ムと通信するためのプロトコルはあるが、アプリケーションはハードウェアと直接やり取 りできる。実際、プログラマはハードウェアと直接やり取りする。また、当時、Windows 95 市場は Windows NT よりはるかに大きかったため、Windows 95 用のデバイスドライ バは開発しても Windows NT 用には開発しないというおもしろいベンダーも存在した。 デバイスのインストールを容易にする方法の一環として、Microsoft は Win32 ドライバ モデル( WDM )を作り出した。WDM は、デバイスドライバを作成するための統一的な手 1.2 Windows NT のアーキテクチャ 43 法である。WDM により、可能な処理とその実行方法に特定の制限が与えられるが、デバ イスドライバの同じバイナリを Windows 98 と Windows 2000 の両方で実行することが 可能になる。詳細については、第 30 章「 WDM 」で説明する。 要するに、本書では、すべての階層を正しく並べ、プロトコルを正しく理解し、堅牢で 信頼性が高く正しいデバイスドライバを構築する方法について説明する。 1.2 Windows NTのアーキテクチャ Windows NT は、Intel 80386 および MIPS プラットフォーム向けの最新のオペレーティ ングシステムを構築するという野心的なプロジェクトとしてスタートした。このとき、次 に示す目標が明らかになった。 ● Intel プラットフォームには制約が多く、短命であると考えられたため、オペレーティ ングシステムはほかのプロセッサのアーキテクチャへの移植が可能でなければならな い。これは、ほとんどのコードを C で書くことを意味する。 INFORMATION 予言は常に予言者の期待を裏切るものである。Intel アーキテクチャは今でも健在であり、パー ソナルコンピュータの世界を形成する主要勢力である。MIPS や PowerPC など、Windows NT が動作し、期待されていたほかのアーキテクチャはそれほど人気がないことが明らかになり、 Microsoft は、Windows 2000 でこの 2 つのプラットフォームをサポートしない予定であると 発表した。これは、PowerPC アーキテクチャを支持する Motorola と IBM が PowerPC ベー スのサーバーからの撤退を決めた一因でもある。これにより、Windows NT を実行するアーキ テクチャは、Intel の x86 ファミリと Alpha の 2 つだけになった。Hewlett-Packard と Intel が共同で開発している 64 ビットのアーキテクチャである Merced チップでは、Windows NT が動作する。 ● デバイスドライバの多くは C でコーティングされることになる。 INFORMATION これはおおむね正しい。デバイスドライバをアセンブリでコーディングする必要はない。コン ピュータに依存する非常にささいな部分は、本書全体を通じて詳しく説明する特定のコンポー ネント、つまりハードウェアアブストラクションレイヤ( HAL )によって処理される。VGA ( SVGA を除く)対応のディスプレイドライバだけは大部分がアセンブリ*7 で書かれたが、こ れは難しさとコストに見合うパフォーマンスの向上が得られたからである。 ● オペレーティングシステムの信頼性を高くしなければならない。これは、アプリケー ションが相互に干渉しないことを意味する。 *7 アセンブリのコードは 1.42M バイト、C のコードは 360K バイトである 44 第1章 ドライバの概要 ● オペレーティングシステムには安全性が求められる。これは、ユーザーは権利が与え られていないリソースを操作できないことを意味する。オペレーティングシステムの セキュリティ(すべてのオペレーティングシステムがユーザーから保護される)とユー ザー間のセキュリティ( 明示的に許可されない限り、ユーザーは別のユーザーに属す リソースにアクセスしたり、変更することはできない)の両方がこれに含まれる。 INFORMATION 伝統的に、セキュリティはファイルシステムの機能であり、ファイルが保護の基本単位であっ た。Windows NT では、オペレーティングシステムによって管理されるさまざまな種類のリ ソースが同じセキュリティのパラダイムの対象になり、ファイルよりはるかに細かいレベル で実装されている。このセキュリティはデバイスに対しても適用されるが、デバイスドライ バの開発には関係のないレベルである。デバイスドライバが呼び出された場合には、呼び出 し元はその権利を与えられているとみなしてもよい。 ● オペレーティングシステムはマルチプロセッサオペレーティングシステムでなければ ならない。マルチプロセッサアーキテクチャとは、共有メモリを持つ対称型マルチプ ロセッサ( SMP )である。デバイスドライバの開発では、コーディング時に重要な意 味を持つため、この設計要件をはっきりと意識しなければならない。詳細については、 後述する。 ● オペレーティングシステムはパフォーマンスについて特定の条件を課せられる。たと えば、コンピュータが割り込みに対して無視する時間の最小値を決めなければならな い。この要件を満たすためには、特定のプロトコルに従わなければならないことを意 味する。プロトコルに基づいてドライバを正しくコーディングしなければ、リアルタ イムオーディオデバイスなど、この仕様に依存するほかのデバイスドライバが深刻な 誤動作を起こす可能性がある。これは、アプリケーションは相互に干渉しないという 原則に違反することになる。この方法についても、後述する。 1.3 優先度 Windows NT には 2 つのレベルの優先度モデルがある。高いレベルの優先度はハード ウェアおよびソフトウェアの割り込みによって制御され、低いレベルの優先度はスケジュー ラの優先度になる。 実行中のコードは常に特定の割り込み要求レベル( IRQL )で動作する。動作するレベル によって、実行できる処理、タイムスライススケジューラの対象になるかどうか、ほかの 実行スレッドとの関係などが決まる。 IRQL のもっとも高いレベルは、ハードウェア割り込みに対応するデバイス割り込み要 求レベル( DIRQL )である。そのほかの IRQL はソフトウェアで実装される。 割り込みの IRQL は、割り込みが処理されるタイミングを制御する。プロセッサがよ り高いレベルの割り込みを処理しているときには、割り込みは処理されない。IRQL の範囲は