インタロック キューのセットアップと使用
新しいドライバーは、このセクションで説明する方法よりも、 キャンセルセーフIRPキュー フレームワークを優先して使用する必要があります。
ほとんどのシステムFSDのように、デバイス専用スレッドを持つドライバーやエグゼクティブワーカースレッドを使用するドライバーは、インターロックされたキューでIRPの独自のランタイム内部キューイングを管理する可能性が最も高いドライバーのタイプです。 WDMドライバーを含むすべてのPnPドライバーも、PnPと電源状態の移行を行う間、特定のIRPを内部でキューに入れる必要があります。
通常、これらのドライバーは、2重にリンクされたインターロックキューを設定します。すべてのIRPは、 LIST_ENTRYタイプのメンバーを含み、ドライバーは、現在保持しているIRPを2重にリンクするために使用できます。 ドライバーは、片方向リンクされたインターロックキューを設定すると、再試行のために IRP をリクエストすることはできません。
ドライバーは、デバイスの初期化時に、そのインターロックされたキューを設定しなければなりません。 次の図は、二重にリンクされたインターロックキューと、そのようなキューを設定するためにドライバーが呼び出さなければならないサポートルーチン、および、キューへのIRPの挿入とキューからのIRPの削除のためにドライバーが呼び出すことができる ExInterlockedXxx ルーチンのセットを示しています。
この図に示すように、ドライバーは、二重にリンクされたインターロックキューを設定するために、キュー自身と以下のためのストレージを提供しなければなりません。
ドライバーは KeInitializeSpinLock を呼び出して初期化しなければなりません。 通常、ドライバーは、 AddDevice ルーチンでデバイスオブジェクトのデバイス拡張を設定するときにスピンロックを初期化します。
ドライバーが InitializeListHeadを呼び出して初期化する必要があるキューのリストの先頭
二重にリンクされたインターロックキューを使用するほとんどのドライバーは、ドライバーが作成したデバイスオブジェクトのデバイス拡張に必要なストレージを提供します。 キューとエグゼクティブスピンロックは、(ドライバーが controller objectを使用する場合) コントローラ拡張か、ドライバーによって割り当てられた非ページプールに置くことができます。
ドライバーが I/O 要求を受け付けている間、 ListHead が LIST_ENTRYタイプであれば、前の図に示すように、以下のサポートルーチンのいずれかを呼び出すことで、キューに IRP を挿入することができます:
ExInterlockedInsertTailList でIRPをキューの末尾に配置します
ExInterlockedInsertHeadList でIRPをキューの先頭に配置します。 ドライバーは通常、特定の要求を再試行しなければならない場合にのみ、このルーチンを呼び出します。
ドライバーは、IRP (ListEntry)へのポインターと、以前に初期化した ListHead およびエグゼクティブスピンロック (Lock) へのポインターを、これらの ExInterlockedInsertXxxList ルーチンのそれぞれに渡さなければなりません。 ドライバーが ExInterlockedRemoveHeadListを呼び出して IRP をデキューするときは、 ListHead と Lock へのポインターだけが必要です。 デッドロックを防止するために、ドライバーは、 ExInterlockedXxx ルーチンに渡すExecutiveSpinLockを保持してはなりません。
インターロックされたキューはエグゼクティブスピンロックによって保護されているため、ドライバーは IRQL = DISPATCH_LEVEL 以下で実行されている任意のドライバールーチンから、二重にリンクされたキューに IRP を挿入し、マルチプロセッサセーフな方法で IRP を削除することができます。
前の図に示されているように、 LIST_ENTRYタイプのListHeadを持つキューは、二重にリンクされたリストです。 SLIST_HEADER タイプのListHeadを持つものは、シーケンスされた単一リンクリストです。 ドライバーは、 ExInitializeSListHeadを呼び出すことで、シーケンスされた単一リンクインタロックキューのListHeadを初期化します。
I/O 操作を決して再試行しないドライバーは ExInterlockedPushEntrySList と ExInterlockedPopEntrySList を使用して、シーケンスされた単一リンクインターロックキューの内部で IRP のキューイングを管理することができます。 このタイプの連動キューを使用するドライバーは、 previous figureに示すように、 SLIST_HEADER タイプのListHeadとExecutiveSpinLockのための常駐ストレージも提供しなければなりません。 ExInterlockedPushEntrySList を呼び出して最初のエントリをキューに挿入する前に、スピンロックを初期化してキューを設定する必要があります。
詳細細についてはは、 ハードウェア優先度の管理 と スピンロックを参照してください。 特定のサポートルーチンのIRQL要件については、そのルーチンのリファレンス ページを参照してください。