トレーニング
モジュール
Troubleshoot device driver failures - Training
This module focuses on the role of device drivers and troubleshooting problems that pertain to them.
このブラウザーはサポートされなくなりました。
Microsoft Edge にアップグレードすると、最新の機能、セキュリティ更新プログラム、およびテクニカル サポートを利用できます。
このトピックでは、学習目的で設計されたカーネル モード ドライバー フレームワーク (KMDF) ドライバーとユーザー モード ドライバー フレームワーク (UMDF) ドライバーを含む Toaster サンプルのコード チュートリアルを提供します。
このサンプルには、Toaster バス ドライバーとファンクション ドライバーを操作するアプリケーションが含まれています。 これらのアプリケーションは、KMDF と UMDF の両方の Toaster バージョンで動作します。
KMDF バス ドライバーは、Toaster バス コントローラーにサービスを提供し、接続されているデバイスを列挙し、バスレベルの電源管理を実行します。 バス ドライバーは、D0 と D3 の電源状態をサポートしています。 また、WMI インターフェイスも備えています。 このディレクトリには、Toaster バス ドライバーの 2 つの異なる実装を示す 2 つのサブディレクトリが含まれています。
Static
バス ドライバーの静的バージョンは、フレームワークによって提供される静的な子リスト (デバイスごとに 1 つ) を使用して子デバイスを列挙する方法を示しています。
静的列挙により、ドライバーは初期化中にデバイスの存在を検出して報告できます。ただ、システム構成に対するその後の変更を報告する機能は限られています。
バス ドライバーは、デバイスまたは機能サブユニットの数と種類が事前に定義され、永続的であり、ドライバーが実行されているシステムの構成に依存しない場合は、静的列挙を使用できます。
たとえば、サウンド カードのドライバーがバス ドライバーとして機能し、MIDI、オーディオ、ジョイスティックなどのカードの機能ごとに個別の物理デバイス オブジェクト (PDO) を作成する場合があります。
子を列挙するには、バス ドライバーは以下を実施します。
WdfPdoInitAllocate を呼び出して、WDFDEVICE_INIT 構造体を取得します。
WDFDEVICE_INIT 構造体を初期化します。
WdfDeviceCreate を呼び出して、PDO を表すフレームワーク デバイス オブジェクトを作成します。
WdfDeviceCreate を呼び出した後、ドライバーは WdfFdoAddStaticChild を呼び出して子デバイスを子リストに追加します。
ドライバーは、事前に定義された永続的なデバイス構成にのみ静的子リストを使用する必要があるため、通常、ドライバーは作成後に静的な子リストを変更しません。 ドライバーが子デバイスにアクセスできなくなったと判断した場合、ドライバーは WdfPdoMarkMissing を呼び出すことができます。 (子デバイスが、アクセス可能でも応答しない場合、ドライバーは WDF_DEVICE_STATE 構造体の失敗したメンバーを WdfTrue に設定し、WdfDeviceSetDeviceState を呼び出す必要があります)
バス ドライバーが起動するたびに子デバイスを静的に列挙するには、トースター バス Inf ファイルを使用してこの値を構成します。 このレジストリ設定を使用して列挙できる子デバイスの最大数は 10 です。
[ToasterStatBus_Device.NT.HW]
AddReg=ToasterStatBus_Device.NT.AddReg
[ToasterStatBus_Device.NT.AddReg]
HKR,,NumberOfToasters,0x10001,2
動的
バス ドライバーの動的バージョンは、子リスト オブジェクトを使用して子デバイスを列挙する方法を示しています。
動的列挙により、ドライバーは、システムの実行中にシステムに接続されているデバイスの数と種類の変更を検出して報告できます。
親デバイスに接続されているデバイスの数または種類がシステムの構成に依存する場合、バス ドライバーは動的列挙を使用する必要があります。 これらのデバイスの中には、常時システムに接続されているデバイスもあれば、システムの実行中に電源に接続されたり取り外されたりするものもあります。
たとえば、システムの PCI バスに接続されているデバイスの数と種類はシステムに依存しますが、ユーザーが電源をオフにしてケースを開き、ドライバーを使用してデバイスを追加または削除しない限り、それらは永続的です。 一方、ユーザーは、システムの実行中にケーブルを接続または取り外すことによって、USB デバイスを追加または取り外すことができます。
バス ドライバーは、子デバイスを識別するたびに、子デバイスの説明を子リストに追加する必要があります。 ドライバーは、WdfFdoGetDefaultChildList を呼び出すことによって、フレームワークによって提供されるデバイスの既定の子リストを使用するか、WdfChildListCreate を呼び出すことによって、子をグループ化するための追加の子リストを作成できます。 このサンプルでは、既定の子リストを使用します。 子の説明は、必要な ID の説明とオプションのアドレスの説明で構成されます。
用語 | 説明 |
---|---|
識別の説明は、ドライバが列挙する各デバイスを一意に識別する情報を含む構造体です。 ドライバーはこの構造体を定義しますが、最初のメンバーは WDF_CHILD_IDENTIFICATION_DESCRIPTION_HEADER 構造体である必要があります。 |
|
アドレスの説明は、デバイスが接続されている間に情報が変更される可能性がある場合に、ドライバーがバス上のデバイスにアクセスできるように、ドライバーが必要とする情報を含む構造体です。 ドライバーはこの構造体を定義しますが、最初のメンバーは WDF_CHILD_IDENTIFICATION_DESCRIPTION_HEADER 構造体である必要があります。 アドレスの説明は省略可能です。 このサンプルでは、アドレスの説明は使用しません。 |
子リストに子を追加するために、ドライバーは、検出された各子デバイスに対して WdfChildListAddOrUpdateChildDescriptionAsPresent を呼び出します。 この呼び出しは、ドライバーが親デバイスに接続されている子デバイスを検出したことをフレームワークに通知します。 ドライバーが WdfChildListAddOrUpdateChildDescriptionAsPresent を呼び出すと、ID の説明と、必要に応じてアドレスの説明が提供されます。
ドライバーが WdfChildListAddOrUpdateChildDescriptionAsPresent を呼び出して新しいデバイスを報告した後、フレームワークは新しいデバイスが存在することを PnP マネージャーに通知します。 その後、PnP マネージャーは、新しいデバイスのデバイス スタックとドライバー スタックをビルドします。 このプロセスの一環として、フレームワークはバス ドライバーの EvtChildListCreateDevice コールバック関数を呼び出します。 このコールバック関数は、新しいデバイスの PDO を作成するために WdfDeviceCreate を呼び出す必要があります。
子デバイスが見つからないことを報告するために、このドライバーは WdfChildListUpdateChildDescriptionAsMissing を呼び出します。 動的列挙の詳細については、フレームワークのドキュメントを参照してください。
関数ドライバーには、wdfsimple と wdffeatured の 2 つの異なるバージョンがあります。 2 つのバージョンの関数ドライバーは、共有ディレクトリ内の共通ヘッダー ファイルを共有します。
WdfSimple
このバージョンでは、ドライバーは PnP イベントと Power イベントを処理せず、代わりにこれらのイベントに対するフレームワークの既定のサポートに依存します。 notify.exe などのアプリケーションは、このドライバーを使用して、ドライバーによって登録されたデバイス インターフェイスを開き、読み取り、書き込み、または IOCTL 要求を送信できます。
WdfFeatured
このバージョンでは、PNP イベントと Power イベントに登録する方法、ファイルの作成要求と終了要求を処理する方法、WMI セット イベントとクエリ イベントを処理する方法、WMI 通知イベントをトリガーする方法を示します。 電源ポリシー所有者であることにより、アイドル通知にも登録されるため、I/O アクティビティがない場合にデバイスを低電力状態にすることができます。
このディレクトリには、2 つのフィルター ドライバーのソース コードが含まれています。 汎用サンプルは、シンプルなパススルー フィルター ドライバーです。 SideBand は、コントロール デバイス オブジェクトを使用してアプリケーションにサイドバンド ioctl インターフェイスを提供する方法を示しています。 このプライベート インターフェイスを使用すると、アプリケーションはフィルター ドライバーと直接通信できます。つまり、フィルターがアタッチされている機能デバイス スタックをバイパスします。 また、SideBand サンプルでは、ドライバーが複数のデバイスの要求を処理する場合に、デバイス オブジェクトのコレクションを実装する方法も示します。 filter.inf を使用して、これらのフィルターを既存の Toaster デバイスにインストールできます。
このサンプルでは、リモート I/O ターゲット インターフェイスを使用して、デバイスを開き、カーネル モードで I/O を実行する方法を示します。 このサンプルでは、IoRegisterPlugPlayNotification を呼び出して、Toaster インターフェイス クラスの PnP 通知コールバック ルーチンを登録します。 Toaster デバイスが接続されると、PnP マネージャーによってコールバックが呼び出されます。 コールバックでは、このサンプルはリモート ターゲットを作成し、コールバック データで提供されるシンボリック リンクを使用してデバイスを開きます。
また、このサンプルではパッシブ タイマーを使用して、ターゲット デバイスへの非同期読み取りと書き込みを示します。 また、I/O ターゲット オブジェクトに EvtIoTargetQueryRemove/、EvtIoTargetRemoveCanceled/、EvtIoTargetRemoveComplete を登録して、デバイス変更通知に応答する方法も示します。 この手法は、ドライバーが制御していない別のデバイスとドライバーが通信する場合に使用できます。 このドライバーは、Wdftoastmon.inf を使用し、ルート列挙デバイスとしてインストールします。 Toaster バス ドライバーと同じ手順をインストールに使用します。
WUDFToaster ドライバーを使用すると、ユーザー アプリケーション (toast/notify.exe) は、ドライバーによって登録されているデバイス インターフェイスを開き、読み取り、書き込み、または IOCTL 要求を送信できます。 このドライバー サンプルでは、PnP イベントと電源イベントに登録し、電源ポリシーの所有権を設定し、I/O 要求を処理する方法も示します。 これは、運用環境での使用を意図していない最小限のドライバー サンプルです。
WUDF Toaster を KMDF Toastmon サンプルと組み合わせて使用し、リモート I/O ターゲットを使用してユーザーモード ドライバーへのカーネルモード クライアント アクセスを示すことができます。
これを行うには、この UMDF ドライバーの INF の .WDF セクションに次の行を追加します: UmdfKernelModeClientPolicy = AllowKernelModeClients
このサンプルは、KMDF ToastMon サンプルの UMDF バージョンです。
UMDF Toastmon では、ユーザーモード ドライバー フレームワークを使用して最小限のドライバーを書き込むために UMDF を使用する方法を示し、ベスト プラクティスを示します。 ドライバーはデバイス (ルート列挙されたもの、または実際のハードウェア デバイス) に正常に読み込まれますが、最小限の PnP 機能を持ち、I/O 操作の受信をサポートしていません。
Toastmon は、他の UMDF ドライバーを書き込む際の学習ツールとして使用されることを目的としています。
トレーニング
モジュール
Troubleshoot device driver failures - Training
This module focuses on the role of device drivers and troubleshooting problems that pertain to them.