WDF ドライバーでの WDM の概念
Windows Driver Frameworks (WDF) は、Microsoft Windows Driver Model (WDM) インターフェイスのラッパーです。 フレームワークは多くの WDM の概念を簡略化し、他の概念を完全に非表示にして操作する必要がないようにしますが、WDM ドライバーの基本的な概念の一部を理解しておく必要があります。 具体的には、ドライバーの種類、ドライバー スタック、デバイス スタック、および I/O 要求パケットについて理解する必要があります。
ドライバーの種類
Windows ベースのドライバーは、バス ドライバー、ファンクション ドライバー、およびフィルター ドライバーの3 種類に別れています。 バス ドライバーは、親バスに接続されている子デバイスを検出し、その特性を報告することによって、I/O バスをサポートします。 (このアクティビティはバス列挙と呼ばれます)。ファンクション ドライバーは、デバイスとバスの I/O 操作を制御します。 フィルター ドライバーは、ユーザー アプリケーションとドライバーの間、または個々のドライバー間で流れるデータを受信、確認、および変更する可能性があります。
バスのドライバーは、基本的に子も列挙するファンクション ドライバーです。 ドライバーは、バス上の子デバイスを列挙するときに、「バス ドライバー」として機能します。 それ以外の場合、同じドライバーは、バス アダプターのハードウェアにアクセスする I/O 操作を処理するときに、バスの「ファンクション ドライバー」として機能します。
ユーザー モード ドライバー フレームワーク (UMDF) ドライバーをバス ドライバーにすることはできません。
ドライバー スタック
Windows オペレーティング システムでは、WDM ドライバーは、ドライバー スタックと呼ばれる垂直呼び出しシーケンスで階層化されます。 スタックの最上位のドライバーは、通常、要求がオペレーティング システムの I/O マネージャーを通過した後、ユーザー アプリケーションから I/O 要求を受信します。 下位のドライバー レイヤーは、通常、コンピューターハードウェアと通信します。
単純なドライバー スタックには、バス固有の I/O 操作を処理し、それに接続されている子デバイスを列挙する、スタックの下部にバス ドライバーが含まれています。 通常、1 つ以上のデバイス固有のファンクション ドライバーがバス ドライバーの上にあります。 これらのファンクション ドライバーは、バスに接続されているデバイスへの I/O 操作を処理します。 フィルター ドライバーは、ファンクション ドライバーの上に配置することも、バス ドライバーとファンクション ドライバーの間に配置することもできます。 実行中のシステムには、さまざまな種類のデバイスをサポートする複数のドライバー スタックがあります。
デバイス スタック
各ドライバー スタックは、1 つ以上のデバイス スタックをサポートします。 デバイス スタックは、WDM で定義された DEVICE_OBJECT 構造体から作成されるデバイス オブジェクトのセットです。 各デバイス スタックは、1 つのデバイスを表します。 各ドライバーは、各デバイスのデバイス オブジェクトを作成し、各デバイス オブジェクトをデバイス スタックにアタッチします。 デバイス スタックは、デバイスが接続および取り外され、システムが再起動されるたびに作成および削除されます。
バス ドライバーは、子デバイスが接続または取り外されたことを検出すると、プラグ アンド プレイ (PnP) マネージャーに通知します。 これに対して、PnP マネージャーは、親デバイス (つまりバス) に接続されている各子デバイスの物理デバイス オブジェクト (PDO) を作成するようにバス ドライバーに要求します。 PDO はデバイス スタックの一番下になります。
次に、PnP マネージャーは関数ドライバーとフィルター ドライバーを読み込んで各デバイスをサポートし (まだ読み込まれていない場合)、PnP マネージャーはこれらのドライバーを呼び出して、それぞれがデバイス オブジェクトを作成してデバイス スタックの先頭に追加できるようにします。 ファンクション ドライバーは、機能デバイス オブジェクト (FDO) を作成し、フィルター ドライバーは、フィルター デバイス オブジェクト (フィルター DOs) を作成します。
I/O マネージャーは、デバイスのドライバーに I/O 要求を送信すると、デバイス スタックの最上位のデバイス オブジェクトを作成したドライバーに要求を渡します。 そのドライバーが次の下位ドライバーに要求を渡すように I/O マネージャーに要求を要求した場合、I/O マネージャーはデバイス スタックを使用して次の下位ドライバーを決定します。 (次の下位ドライバーは、次の下位のデバイス オブジェクトを作成したドライバーです)。
WDF は、WDM デバイス オブジェクトごとにフレームワーク デバイス オブジェクトを作成します。 フレームワーク ベースのドライバーは、WDM デバイス オブジェクトではなく、これらのフレームワーク デバイス オブジェクトにアクセスします。
I/O 要求パケット
I/O マネージャーは、I/O 要求パケット (IRP) を作成して、アプリケーションの I/O 要求をドライバーに送信します。 IRP には、I/O 操作 (読み取り/書き込み操作など) を実行する要求、または I/O コントロール (IOCTL) アクション (状態の返しなど) を実行する要求を含めることができます。 さらに、PnP マネージャーは、ドライバーが実行する必要がある PnP と電源管理操作を表す Irp を作成し、ドライバーにこれらの Irp を送信します。
通常、I/O マネージャーは、ユーザー アプリケーションが読み取り、または書き込み操作を要求するときに、読み取りまたは書き込み IRP を作成します。 I/O マネージャーは、ドライバー スタックの上部にあるドライバーに IRP を渡します。そのドライバーは、要求をサービスするか、次の下位ドライバーに要求を渡します。 一部の要求はスタックの一番下に移動し、一部は上位レベルのドライバーによって完全に処理されます。
ドライバーが IRP を受け取るたびに、ドライバーは、操作を処理する必要があるデバイスを表すデバイス オブジェクトへのポインターも受け取ります。 そのため、ドライバー スタック内のドライバーは、デバイス オブジェクトを使用して、特定の要求が送信されるはずの接続されているデバイスを特定します。
通常、WDF ドライバーは IRP に直接アクセスしません。 フレームワークは、読み取り、書き込み、およびデバイスの I/O 制御操作を表す WDM IRP を、カーネル モード ドライバー フレームワーク (KMDF) および UMDF ドライバーが I/O キューで受信するフレームワーク要求オブジェクトに変換します。 このフレームワークは、PnP と電源管理 IRP を内部的に処理し、イベント コールバック関数を使用して、PnP イベントと電源イベントをドライバーに通知します。