フレームワークベースのドライバーの WDM の概念

カーネル モード ドライバー フレームワーク (KMDF) は、Microsoft Windows Driver Model (WDM) インターフェイスのラッパーです。WDM の概念のうち、多くのものはフレームワークによって単純化され、それ以外のものは完全に隠ぺいされるため、ドライバーでこれらのインターフェイスを操作する必要はありませんが、WDM ドライバーの基本的な概念については、一定の範囲で理解しておく必要があります。具体的には、ドライバーの種類、ドライバー スタック、デバイス スタック、および I/O 要求パケットについて理解しておく必要があります。

ドライバーの種類

Windows ベースのドライバーは、バス ドライバー関数ドライバー、およびフィルター ドライバーの 3 つに分類されます。バス ドライバーは、親バスに接続されている子デバイスを検出し、その特性を報告することによって I/O バスをサポートします (この処理は "バス列挙" と呼ばれます**)。関数ドライバーは、デバイスとバスの I/O 操作を制御します。フィルター ドライバーは、ユーザー アプリケーションとドライバーの間、または個別のドライバー間でやり取りされるデータの受信および確認のほか、場合によっては変更も行います。

バスのドライバーは、実質的に、子の列挙も行う関数ドライバーです。ドライバーがバス上の子デバイスを列挙するとき、そのドライバーは "バス ドライバー" の役割を果たします。一方、同じドライバーがバス アダプターのハードウェアにアクセスする I/O 操作を処理するとき、そのドライバーは "関数ドライバー" の役割を果たします。

ドライバー スタック

Windows オペレーティング システムでは、WDM ドライバーは、"ドライバー スタック" と呼ばれる縦方向の呼び出し順序で階層化されています**。スタック内の最上位のドライバーは、通常、ユーザー アプリケーションからの I/O 要求がオペレーティング システムの I/O マネージャーを通過した後、その要求を受け取ります。下位のドライバー層は、多くの場合、コンピューターのハードウェアと通信します。

単純なドライバー スタックでは、スタックの最下位にバス ドライバーがあります。このドライバーは、バス固有の I/O 操作を処理し、バスに接続されている子デバイスを列挙します。通常、デバイス固有の 1 つ以上の関数ドライバーが、バス ドライバーの上位に配置されます。これらの関数ドライバーは、バスに接続されたデバイスに対する I/O 操作を処理します。フィルター ドライバーは、関数ドライバーの上位にある場合と、バス ドライバーと関数ドライバーの間にある場合があります。実行中のシステムには、さまざまな種類のデバイスをサポートする複数のドライバー スタックがあります。

デバイス スタック

各ドライバー スタックは、1 つ以上の "デバイス スタック" をサポートしています**。デバイス スタックは、WDM で定義されている DEVICE_OBJECT 構造体から作成される一連の "デバイス オブジェクト" です**。各デバイス スタックは、1 つのデバイスを表します。各ドライバーは、管理下にあるデバイスごとにデバイス オブジェクトを作成し、各デバイス オブジェクトをデバイス スタックに割り当てます。デバイス スタックは、デバイスが接続または接続解除されたときに、それぞれ作成、削除されるほか、システムがリブートされたときにも毎回作成および削除されます。

バス ドライバーは、子デバイスの接続または接続解除を検出すると、そのことをプラグ アンド プレイ (PnP) マネージャーに通知します。これを受けて、PnP マネージャーは、親デバイス (つまりバス) に接続されている各子デバイスの物理デバイス オブジェクト (PDO) を作成するよう、バス ドライバーに要求します。この PDO は、デバイス スタックの最下位に配置されます。

次に、PnP マネージャーは、各デバイスをサポートする関数ドライバーとフィルター ドライバーを読み込み (まだ読み込まれていない場合)、これらのドライバーを呼び出します。これにより、各ドライバーがデバイス オブジェクトを作成して、デバイス スタックの最上位に追加できるようになります。関数ドライバーは機能デバイス オブジェクト (FDO) を作成し、フィルター ドライバーはフィルター デバイス オブジェクト (フィルター DO) を作成します。

I/O マネージャーは、I/O 要求をデバイスのドライバーに送信するときに、デバイス スタック内の最上位のデバイス オブジェクトを作成したドライバーに要求を渡します。そのドライバーが、要求を次の下位ドライバーに渡すよう I/O マネージャーに要求すると、I/O マネージャーは、デバイス スタックを使用して次の下位ドライバーを特定します (次の下位ドライバーは、次の下位デバイス オブジェクトを作成したドライバーです)。

カーネル モード ドライバー フレームワークは、各 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 を受信するたびに、その操作の処理を担当するデバイスを表すデバイス オブジェクトへのポインターも受け取ります。このため、ドライバー スタック内のドライバーは、デバイス オブジェクトを使用して、接続されているデバイスのうち特定の要求を担当するデバイスを判断します。

フレームワークベースのドライバーが IRP に直接アクセスすることは、通常はありません。カーネル モード ドライバー フレームワークは、読み取り、書き込み、およびデバイス I/O 制御の各操作を表す WDM IRP を、フレームワーク要求オブジェクトに変換します。ドライバーは、このオブジェクトを I/O キューで受信します。フレームワークは、PnP および電源管理の IRP を内部的に処理し、イベント コールバック関数を使用して、PnP および電源に関するイベントをドライバーに通知します。