次の方法で共有


デバイス ノードとデバイス スタック

Windows では、デバイスはプラグ アンド プレイ (PnP) デバイス ツリーのデバイス ノードによって表されます。 通常、I/O 要求がデバイスに送信されると、複数のドライバーが要求を処理するのに役立ちます。 これらのドライバーはそれぞれデバイス オブジェクトに関連付けられ、デバイス オブジェクトはスタックに配置されます。 デバイス オブジェクトとそれに関連付けられているドライバーのシーケンスは、デバイス スタックと呼ばれます。 各デバイス ノードには、独自のデバイス スタックがあります。

デバイス ノードとプラグ アンド プレイ デバイス ツリー

Windows では、 プラグ アンド プレイ デバイス ツリーと呼ばれるツリー構造でデバイスを整理するか、単に デバイス ツリーを構成します。 通常、デバイス ツリー内のノードは、複合デバイス上のデバイスまたは個々の関数を表します。 ただし、一部のノードは、物理デバイスと関連付けのないソフトウェア コンポーネントを表します。

デバイス ツリー内のノードは、 デバイス ノードと呼ばれます。 デバイス ツリーのルート ノードは、 ルート デバイス ノードと呼ばれます。 規則により、ルート デバイス ノードは、次の図に示すように、デバイス ツリーの下部に描画されます。

デバイス ノードを示すデバイス ツリーの図。

デバイス ツリーは、PnP 環境に固有の親子関係を示しています。 デバイス ツリー内のいくつかのノードは、子デバイスが接続されているバスを表します。 たとえば、PCI Bus ノードは、マザーボード上の物理 PCI バスを表します。 起動中、PnP マネージャーは PCI バス ドライバーに PCI バスに接続されているデバイスを列挙するように求めます。 これらのデバイスは、PCI Bus ノードの子ノードによって表されます。 上の図では、PCI Bus ノードには、USB ホスト コントローラー、オーディオ コントローラー、PCI Express ポートなど、PCI バスに接続されている複数のデバイスの子ノードがあります。

PCI バスに接続されている一部のデバイスは、バス自体です。 PnP マネージャーは、これらの各バスに接続されているデバイスを列挙するように求めます。 上の図では、オーディオ コントローラーが、オーディオ デバイスが接続されているバスであることがわかります。 PCI Express ポートはディスプレイ アダプターが接続されているバスであり、ディスプレイ アダプターは 1 台のモニターが接続されているバスであることがわかります。

ノードがデバイスとバスのどちらを表していると考えるかは、観点によって異なります。 たとえば、ディスプレイ アダプターは、画面に表示されるフレームを準備する際に重要な役割を果たすデバイスと考えることができます。 ただし、ディスプレイ アダプターは、接続されたモニターを検出して列挙できるバスと考えることができます。

デバイス オブジェクトとデバイス スタック

デバイス オブジェクトは、DEVICE_OBJECT構造体のインスタンスです。 PnP デバイス ツリー内の各デバイス ノードには、デバイス オブジェクトの順序付けられた一覧があり、これらの各デバイス オブジェクトはドライバーに関連付けられています。 デバイス オブジェクトの順序付けられた一覧とそれに関連付けられているドライバーは、デバイス ノードの デバイス スタック と呼ばれます。

デバイス スタックは、いくつかの方法で考えることができます。 最も正式な意味では、デバイス スタックは (デバイス オブジェクト、ドライバー) ペアの順序付きリストです。 ただし、特定のコンテキストでは、デバイス スタックをデバイス オブジェクトの順序付きリストと考えると便利な場合があります。 他のコンテキストでは、デバイス スタックをドライバーの順序付きリストと考えると便利な場合があります。

慣例により、デバイス スタックには上と下があります。 デバイス スタックに作成される最初のデバイス オブジェクトが下部にあり、デバイス スタックに作成されてアタッチされる最後のデバイス オブジェクトが一番上にあります。

次の図では、Proseware Gizmo デバイス ノードに、3 つの (デバイス オブジェクト、ドライバー) ペアを含むデバイス スタックがあります。 最上位のデバイス オブジェクトはドライバー AfterThought.sysに関連付けられます。中央のデバイス オブジェクトはドライバー Proseware.sysに関連付け、下部のデバイス オブジェクトはドライバー Pci.sysに関連付けられます。 図の中央にある PCI Bus ノードには、2 つの (デバイス オブジェクト、ドライバー) ペア (Pci.sys に関連付けられたデバイス オブジェクトと、Acpi.sysに関連付けられたデバイス オブジェクト) を含むデバイス スタックがあります。

proseware gizmo および pci デバイス ノードのデバイス スタックに並べ替えられたデバイス オブジェクトを示す図。

デバイス スタックはどのように構築されますか?

起動中、PnP マネージャーは、バスに接続されている子デバイスを列挙する各バスのドライバーを要求します。 たとえば、PnP マネージャーは PCI バス ドライバー (Pci.sys) に PCI バスに接続されているデバイスを列挙するように求めます。 この要求に応じて、Pci.sys は PCI バスに接続されている各デバイスのデバイス オブジェクトを作成します。 これらの各デバイス オブジェクトは、 物理デバイス オブジェクト (PDO) と呼ばれます。 Pci.sys が一連の PDO を作成した直後、デバイス ツリーは次の図のようになります。

子デバイスの pci ノードと物理デバイス オブジェクトの図。

PnP マネージャーは、デバイス ノードを新しく作成された各 PDO に関連付け、レジストリを調べて、ノードのデバイス スタックに含める必要があるドライバーを特定します。 デバイス スタックには 1 つの関数 ドライバー (および 1 つだけ) が必要であり、必要に応じて 1 つ以上の フィルター ドライバーを持つことができます。 ファンクション ドライバーは、デバイス スタックのメイン ドライバーであり、読み取り、書き込み、およびデバイス制御の要求を処理します。 フィルター ドライバーは、読み取り、書き込み、およびデバイス制御要求の処理において補助的な役割を果たします。 各関数とフィルター ドライバーが読み込まれると、デバイス オブジェクトが作成され、デバイス スタックにアタッチされます。 ファンクション ドライバーによって作成されたデバイス オブジェクトは 機能デバイス オブジェクト (FDO) と呼ばれ、フィルター ドライバーによって作成されたデバイス オブジェクトは フィルター デバイス オブジェクト (Filter DO) と呼ばれます。 これで、デバイス ツリーは次の図のようになります。

proseware gizmo デバイス ノード内のフィルター、機能、物理デバイス オブジェクトを示すデバイス ツリーの図。

図では、1 つのノードでは、フィルター ドライバーがファンクション ドライバーの上にあり、もう一方のノードでは、フィルター ドライバーがファンクション ドライバーの下にあることに注意してください。 デバイス スタックのファンクション ドライバーの上にあるフィルター ドライバーは、 上位フィルター ドライバーと呼ばれます。 関数ドライバーの下にあるフィルター ドライバーは、 下位フィルター ドライバーと呼ばれます。

PDO は、常にデバイス スタック内の最下位のデバイス オブジェクトです。 これは、デバイス スタックの構築方法に起因します。 最初に PDO が作成され、追加のデバイス オブジェクトがスタックにアタッチされると、既存のスタックの一番上に接続されます。

手記 デバイスのドライバーがインストールされると、インストーラーは情報 (INF) ファイル内の情報を使用して、どのドライバーがファンクション ドライバーで、どのドライバーがフィルターであるかを判断します。 通常、INF ファイルは Microsoft またはハードウェア ベンダーによって提供されます。 デバイスのドライバーがインストールされた後、PnP マネージャーは、レジストリを調べることによって、デバイスの関数とフィルター ドライバーを決定できます。

バス ドライバー

上の図では、ドライバー Pci.sys が 2 つの役割を果たしていることがわかります。 最初に、Pci.sys は PCI Bus デバイス ノードの FDO に関連付けられます。 実際、PCI Bus デバイス ノードに FDO が作成されました。 そのため、Pci.sys は PCI バスのファンクション ドライバーです。 次に、Pci.sys は PCI Bus ノードの各子の PDO に関連付けられます。 子デバイスの PDO を作成したことを思い出してください。 デバイス ノードの PDO を作成するドライバーは、ノードの バス ドライバー と呼ばれます。

参照ポイントが PCI バスの場合、Pci.sys はファンクション ドライバーです。 ただし、参照ポイントが Proseware Gizmo デバイスの場合は、Pci.sys がバス ドライバーになります。 このデュアル ロールは、PnP デバイス ツリーで一般的です。 バスのファンクション ドライバーとして機能するドライバーは、バスの子デバイスのバス ドライバーとしても機能します。

ユーザー モード デバイス スタック

ここまで、カーネル モード デバイス スタックについて説明してきました。 つまり、スタック内のドライバーはカーネル モードで実行され、デバイス オブジェクトはシステム空間にマップされます。これは、カーネル モードで実行されているコードでのみ使用できるアドレス空間です。 カーネル モードとユーザー モードの違いについては、「 ユーザー モードとカーネル モード」を参照してください。

場合によっては、デバイスには、カーネル モードのデバイス スタックに加えて、ユーザー モードのデバイス スタックがあります。 ユーザー モード ドライバーは、多くの場合、Windows Driver Framework (WDF) によって提供されるドライバー モデルの 1 つである User-Mode Driver Framework (UMDF) に基づいています。 UMDF では、ドライバーはユーザー モード DLL であり、デバイス オブジェクトは IWDFDevice インターフェイスを実装する COM オブジェクトです。 UMDF デバイス スタック内のデバイス オブジェクトは 、WDF デバイス オブジェクト (WDF DO) と呼ばれます。

次の図は、USB-FX-2 デバイスのデバイス ノード、カーネル モード デバイス スタック、およびユーザー モード デバイス スタックを示しています。 ユーザー モード スタックとカーネル モード スタックの両方のドライバーは、USB-FX-2 デバイスに送信される I/O 要求に参加します。

ユーザー モードとカーネル モードのデバイス スタックを示す図。

すべてのドライバー開発者向けの の概念

ドライバー スタック