IRP のキューとデキュー

I/O マネージャーは、マルチタスクおよびマルチスレッド システム内の非同期 I/O をサポートしているため、デバイスへの I/O 要求は、デバイスのドライバーでそれらが完了するまでに処理されるよりも高速に処理される場合があります (特にマルチプロセッサ マシンの場合)。 したがって、デバイスが別の IRP の処理でビジー状態になっている場合は、特定のデバイスにバインドされている IRP をそのドライバーでキューに登録する必要があります。

そのため、最下位レベルのドライバーには、次のいずれかが必要です。

  • ドライバーがシステム提供の IRP キューにキューに入れた IRP の I/O 操作を開始するために I/O マネージャーが呼び出す StartIo ルーチン (IoStartPacket を参照)。

  • 内部 IRP キューとデキュー メカニズム。ドライバーが、その対応能力を超える速さで入ってくる IRP を扱うために使用します。 ドライバーは、デバイス キュー、インターロックされたキュー、またはキャンセルセーフ キューを使用できます。 詳細については、「ドライバーによって管理される IRP キュー」を参照してください。

ディスパッチ ルーチン内で想定されるすべての IRP に対応し、完了できる最下位レベルのデバイス ドライバーのみ、StartIo ルーチンや IRP のドライバー管理キューが不要です。

ほとんどの上位レベルのドライバーには、StartIo ルーチンがありません。 ほとんどの中間ドライバーに、StartIo ルーチンも内部キューもありません。中間ドライバーは通常、ディスパッチ ルーチンから渡された有効なパラメーターがある IRP を渡し、IoCompletion ルーチンの IRP に必要な後処理を実行します。

以下の項では、一般に、Irp の内部のドライバーで管理されるキューを備えた StartIo ルーチンを実装するかどうかを決定するための設計上の注意点を説明します。

ドライバーの StartIo ルーチン

一度に 1 つのデバイス I/O 操作のみを処理できるコンピューター周辺機器の場合、デバイス ドライバーは StartIo ルーチンを実装できます。 これらのドライバーの場合、I/O マネージャーは、システム提供の IRP キューとの間で IRP をエンキューし、デキューする IoStartPacket ルーチンと IoStartNextPacket ルーチンを提供します。

StartIo ルーチンの詳細については、「StartIo ルーチンの作成」を参照してください。

ドライバーの IRP の内部キュー

デバイスが複数の同時 I/O 操作をサポートできる場合、その最下位レベルのデバイス ドライバーでは、内部要求キューをセットアップし、専用の IRP キューを管理する必要があります。 たとえば、システム シリアル ドライバーは、全二重シリアル デバイスをサポートしているため、そのデバイスの読み取り、書き込み、消去、および待機操作用に別々のキューが用意されています。

一部の下位デバイス ドライバーに要求を送る上位レベルのドライバーでは、IRP の内部キューも維持管理される場合もあります。 たとえば、ファイル システム ドライバーには、ほとんどの場合、IRP の内部キューがあります。

詳細については、「ドライバーによって管理される IRP キュー」を参照してください。

内部キューの同期

通常、デバイス専用スレッドを持つドライバーと、エグゼクティブ ワーカー スレッド (ほとんどのファイル システム ドライバーを含む) を使用する最上位レベルのドライバーは、IRP 用に専用のキューをセットアップします。 キューは、ドライバー スレッドまたはドライバーが提供するワーカー スレッド コールバック、および IRP を処理する他のドライバー ルーチンによって共有されます。

専用のキュー構造を実装するドライバーでは、キューへのアクセスを同期し、取り消された IRP がキューから削除する必要があります。 ドライバー ライターのためにこのタスクを簡略化するため、IRP キューを実装するときに使用できる標準フレームワークとしてキャンセルセーフ IRP キューがあります。 詳細については、「キャンセルセーフ IRP キュー」を参照してください。 これは、IRP キューの実装に推奨される方法です。

ドライバーは、すべての IRP キューの同期を実装し、ロジックを明示的に取り消すこともできます。 たとえば、ドライバーは、インターロックされたキューを使用できます。 ドライバーのディスパッチ ルーチンが、インターロックされたキューに IRP を挿入し、ドライバーが作成したスレッドまたはドライバーのワーカー スレッド コールバックが、ExInterlockedXxxList サポート ルーチンを呼び出してそれらを削除します。

たとえば、システム フロッピー コントローラー ドライバーは、インターロックされたキューを使用します。 そのデバイス専用スレッドは、他のデバイス ドライバーの StartIo ルーチンで実行される IRP の同じ処理と、他のデバイス ドライバーの DpcForIsr ルーチンで実行される IRP の同じ処理の一部を処理します。

ドライバーの StartIo ルーチンを使用した内部キュー

専用の内部キューを管理するドライバーには、StartIo ルーチンを設定できますが、その必要はありません。 ほとんどの最下位レベルのデバイス ドライバーは、StartIo ルーチンがあるか、IRP の独自のキューを管理しますが、その両方の機能があるわけではありません。

例外としては、STARTIo ルーチンがあり、IRP の内部キューを管理する SCSI ポート ドライバーがあります。 I/O マネージャーは、SCSI HBA を表すドライバーによって作成されたデバイス オブジェクトに関連付けられているデバイス キュー内のポート ドライバーの StartIo ルーチンに IRP をキューします。 また、SCSI ポート ドライバーは、マシン内の HBA 駆動 SCSI バス上の各ターゲット デバイス (SCSI 論理ユニットに対応) に対する IRP のデバイス キューをセットアップし、管理します。

SCSI ポート ドライバーは、その補助デバイス キューを使用して、SCSI バス上の任意のデバイスが特にビジー状態の場合は常に、LU 固有のキューで SCSI クラス ドライバーから送信された IRP を保持します。 実際には、このドライバーの補助 LU 固有のデバイス キューにより、SCSI ポート ドライバーは、HBA で異種 SCSI デバイスの操作をシリアル化しつつ、その HBA の SCSI バス上の各デバイスをできるだけビジー状態に保ちます。