次の方法で共有


デバイス キューのセットアップと使用

ドライバーは、ドライバーまたはデバイスの初期化時に KeInitializeDeviceQueue を呼び出してデバイスキューオブジェクトを設定します。 デバイスの起動後、ドライバーは KeInsertDeviceQueue または KeInsertByKeyDeviceQueueを呼び出して、このキューにIRPを挿入します。 次の図は、これらの呼び出しを示します。

setting up and using device queues.

この図が示すように、ドライバーは常駐する必要があるデバイスキューオブジェクトのストレージを提供する必要があります。 デバイスキューオブジェクトを設定するドライバーは通常、ドライバーが作成したデバイスオブジェクトの デバイス拡張 に必要なストレージを提供しますが、ドライバーが コントローラー オブジェクト を使用する場合はコントローラ拡張に、またはドライバーが割り当てた非ページドプールにストレージを確保することができます。

ドライバーがデバイスキューオブジェクトのストレージをデバイス拡張に提供する場合、デバイスオブジェクトを作成した後、デバイスを起動する前に KeInitializeDeviceQueue を呼び出します。 言い換えると、ドライバーは AddDevice ルーチンから、またはPnP IRP_MN_START_DEVICE 要求を処理するときに、キューを初期化することができます。 KeInitializeDeviceQueueの呼び出しで、ドライバーはデバイスキューオブジェクトに提供するストレージへのポインターを渡します。

デバイスを起動した後、ドライバーは、キューの末尾にIRPを挿入する KeInsertDeviceQueueを呼び出してデバイス キューに IRP を挿入できます。または、前の図に示すように、 ドライバーによって決定された SortKey 値に従って IRP をキューに配置する KeInsertByKeyDeviceQueueを呼び出してIRPをキューの末尾に挿入します。

これらのサポートルーチンはそれぞれ、IRPがキューに挿入されたかどうかを示すブール値を返します。 また、これらの呼び出しのそれぞれは、キューが現在空の(ビジーではない)場合、デバイスキューオブジェクトの状態を ビジー に設定します。 ただし、キューが空 (ビジーではない) の場合、 KeInsertXxxDeviceQueue ルーチンのいずれも、IRPをキューに挿入しません。 代わりに、デバイス キュー オブジェクトの状態をビジー状態に設定し、 FALSE を返します。 IRPはキューイングされていないため、ドライバーはIRPを別のドライバールーチンに渡して処理させる必要があります。

補足的なデバイスキューを設定する場合は、次の実装ガイドラインに従ってください:

KeInsertXxxDeviceQueue への呼び出しが FALSEを返した場合、呼び出し元は、さらなる処理のために、キューに入れようとしたIRPを別のドライバールーチンに渡さなければなりません。 しかし、 KeInsertXxxDeviceQueue の呼び出しは、デバイスキューオブジェクトの状態をビジーに変更するため、ドライバーが KeRemoveXxxDeviceQueue を最初に呼び出さない限り、次に来るIRPはキューに挿入されます。

デバイスキューオブジェクトの状態がビジー状態に設定されている場合、ドライバーは、次のサポートルーチンのいずれかを呼び出すことで、さらなる処理のためにIRPをキューから削除するか、状態を ビジーでない状態にリセットすることができます:

  • KeRemoveDeviceQueue でキューの先頭にあるIRPを削除します。

  • KeRemoveByKeyDeviceQueue で、ドライバーが決定した SortKey 値に従って選択されたIRPを削除する

  • KeRemoveEntryDeviceQueue で、キュー内の特定のIRPを削除するか、または特定のIRPがキュー内にあるかどうかを判断する。

    KeRemoveEntryDeviceQueue は、IRPがデバイスキューにあったのかを示すブール値を返します。

これらルーチンのいずれかを呼び出して、空であるがビジーであるデバイスキューからエントリを削除すると、キューの状態がビジーではない状態に変更されます。

各デバイスキューオブジェクトは、組み込みのエグゼクティブスピンロックによって保護されています ( デバイスキューオブジェクトの使用 の図には示されていません)。 その結果、ドライバーはIRQL = DISPATCH_LEVEL以下で実行されているドライバールーチンから、マルチプロセッサセーフな方法でIRPをキューに挿入したり、削除したりすることができます。 このIRQL制限のため、ドライバーは、DIRQLで実行されるISRまたは SynchCritSection ルーチンから KeXxxDeviceQueue ルーチンを呼び出すことはできません。

詳細は、 ハードウェア優先度の管理 および スピン ロック を参照してください。 特定のサポートルーチンのIRQL要件については、そのルーチンのリファレンス ページを参照してください。