I/O キューの使用例

ドライバーは、システムに接続され特定のドライバーでサポートされている各デバイスに対して、I/O キューと要求ハンドラーの次の組み合わせを使用できます。

  • 単一の既定の I/O キューと単一の要求ハンドラー (EvtIoDefault)。フレームワークは、デバイスの要求をすべて既定のキューに送信し、ドライバーの EvtIoDefault ハンドラーを呼び出して各要求をドライバーに送信します。

  • 単一の既定の I/O キューと複数の要求ハンドラー (EvtIoReadEvtIoWriteEvtIoDeviceControl など)。フレームワークは、デバイスのすべての要求を既定のキューに送信します。ドライバーの EvtIoRead ハンドラーを呼び出して読み取り要求を送信し、 EvtIoWrite ハンドラーを呼び出して書き込み要求を送信し、EvtIoDeviceControl ハンドラーを呼び出してデバイス I/O 制御要求を送信します。

  • 複数の I/O キュー (読み取り要求の I/O キューと書き込み要求の I/O キューなど)。各キューが受信する要求は 1 種類のみであるため、ドライバーは各キューに 1 つの要求ハンドラーのみを提供します。

  • 複数の I/O キュー。それぞれに複数の要求ハンドラーがあります。

シナリオの例のいくつかを次に示します。

単一の順次 I/O キュー

複数の順次 I/O キューと手動キュー

単一の並列 I/O キュー

複数の並列 I/O キュー

単一の順次 I/O キュー

読み取り要求および書き込み要求を一度に 1 つのみ処理するディスク ドライブの関数ドライバーを作成する場合、この関数ドライバーでデバイスごとに必要な I/O キューは 1 つだけです。

ドライバーでは、WdfIoQueueCreate を呼び出し、キューの WDF_IO_QUEUE_CONFIG 構造体で DefaultQueue を TRUE に設定するときにフレームワークで作成される既定の I/O キューを使用できます。WDF_IO_QUEUE_CONFIG 構造体では、ドライバーは次のものも指定する必要があります。

  • WdfIoQueueDispatchSequential: ディスパッチ方法であり、この指定により、既定の I/O キューは I/O 要求をドライバーに同期的に送信します。

  • EvtIoDefault: 単一のイベント コールバック関数であり、すべての I/O 要求を受信します。

ドライバーの既定の I/O キューで I/O 要求が使用できるようになるたびに、フレームワークはドライバーの EvtIoDefault 要求ハンドラーを呼び出して、要求をドライバーに送信します。キューで別の要求が使用可能になっても、ドライバーが以前に送信された要求に対して WdfRequestComplete を呼び出すまで、フレームワークは要求を送信しません。

複数の順次 I/O キューと手動キュー

ここでは、次の特性を持つシリアル ポート デバイスについて検討します。

  • 1 つの読み取り操作と 1 つの書き込み操作を同時に実行できる。

  • 複数の読み取り操作または書き込み操作を非同期的に実行できない。

  • 状態情報のデバイス I/O 制御要求を受信できる。デバイスのドライバーでは、これらの要求の一部 (状態変更を待機する要求など) を完了するのに時間がかかる可能性がある。

このデバイスの関数ドライバーは、デバイスごとに複数の順次 I/O キューを使用できます。ドライバーは WdfIoQueueCreate を 3 回呼び出します。1 回の呼び出しで既定のキューが作成され、2 回の呼び出しで 2 つの追加 I/O キューが作成されます。これらの各キューの WDF_IO_QUEUE_CONFIG 構造体では、ドライバーは次のものを指定する必要があります。

  • WdfIoQueueDispatchSequential: 各キューのディスパッチ方法。この指定により、フレームワークは I/O 要求をドライバーに同期的に送信します。

  • キューごとに異なる要求ハンドラー (EvtIoDefaultEvtIoRead、および EvtIoWrite): キューの I/O 要求を受信します。

ドライバーは WdfIoQueueCreate を呼び出した後、WdfDeviceConfigureRequestDispatching を 2 回呼び出して、すべての読み取り要求を追加のキューの 1 つに転送し、すべての書き込み要求をもう 1 つのキューに転送することができます。

この構成では、デバイスの既定の I/O キュー EvtIoDefault コールバック関数は、状態情報のデバイス I/O 制御要求のみを受信します。

ドライバーが状態要求を長期間保持する必要がある場合は、4 番目のキューを作成し、ディスパッチ方法として WdfIoQueueDispatchManual を指定できます。ドライバーは待機が必要な情報の要求を受信すると、状態情報が使用可能になるまでその要求をこの追加のキューに配置できます。その後、ドライバーはキューから要求を取得し、要求の処理を完了します。その間に、既定のキューは別の要求をドライバーに送信できます。

単一の並列 I/O キュー

IDE ディスク コントローラーには、重複できる I/O 操作と重複できない I/O 操作があります。たとえば、コントローラーはあるディスクで読み取り要求または書き込み要求を処理しているときに、別のディスクにシーク コマンドを送信できます。一方、複数の読み取りコマンドと書き込みコマンドを同時に実行することはできません。

このコントローラーの関数ドライバーは、各 I/O 要求を調べる必要があります。ドライバーはシーク コマンドを受信した場合、そのシーク コマンドを処理できるかどうかを判断する必要があります。次の場合は、シーク コマンドを処理できません。

  • 指定したディスク ドライブが既にビジー状態になっている。

  • ディスク ドライブがフォーマットされているため、他のデバイスをアクティブにできない。

ドライバーは、コントローラーに接続されているデバイスごとに WdfIoQueueCreate を呼び出して既定のキューを作成できます。これらの各キューの WDF_IO_QUEUE_CONFIG 構造体では、ドライバーは次のものを指定する必要があります。

  • WdfIoQueueDispatchParallel: 各キューのディスパッチ方法。この指定により、フレームワークは I/O 要求をドライバーに非同期的に送信します。

  • 各キューの EvtIoDefaultイベント コールバック関数: キューの I/O 要求を受信します。

この構成では、単一の並列 I/O キューが各デバイスに割り当てられます。ドライバーは、フレームワークが各 I/O キューから送信する各 I/O 要求を調べる必要があります。ドライバーが要求を直ちに処理できる場合は、直ちに処理されます。それ以外の場合、ドライバーは WdfIoQueueStop を呼び出します。これにより、ドライバーが WdfIoQueueStart を呼び出すまでフレームワークは要求の送信を停止します。

複数の並列 I/O キュー

SCSI ホスト アダプターは、非同期の重複する I/O 操作をサポートするデバイスの一例です。最大 32 のデバイスをアダプターに接続できます。ここでは、次の構成のシステムについて検討します。

  • SCSI アダプターに接続されているデバイスには、"再選択" をサポートしているものとサポートしていないものがある。SCSI デバイスが再選択をサポートしている場合、アダプターが別のデバイスを処理できるように、デバイスは I/O 操作中にアダプターを一時的に解放できる。最初のデバイスは、後でそれ自体を再選択して操作を完了できる。

  • SCSI アダプターはハードウェアのメールボックスを使用して、ドライバーとデバイスとの間の要求および応答の受け渡しを行う。デバイスで要求の準備ができても、使用可能なメールボックスがない場合、デバイスは待機する必要がある。

パフォーマンスを最適化するために、この SCSI ホスト アダプターの関数ドライバーは、I/O 要求が使用可能になった時点で直ちにフレームワークから I/O 要求を受信する必要があります。ドライバーは各要求を調べ、直ちに開始できるか、デバイスとリソース (メールボックス メモリなど) が使用可能になるまで延期する必要があるかを判定する必要があります。

ドライバーは複数の並列 I/O キューを使用する可能性が高くなります。アダプターに接続されているデバイスごとに、ドライバーは WdfIoQueueCreate を呼び出して既定のキューを作成します。これらの各キューの WDF_IO_QUEUE_CONFIG 構造体では、ドライバーは次のものを指定する必要があります。

  • WdfIoQueueDispatchParallel: 各キューのディスパッチ方法。この指定により、フレームワークは I/O 要求をドライバーに非同期的に送信します。

  • 各キューの EvtIoDefaultイベント コールバック関数: キューの I/O 要求を受信します。

各 I/O キューの EvtIoDefault コールバック関数は、送信時にキューの I/O 要求を調べ、各 I/O 要求を直ちに処理できるかどうかを判定する必要があります。デバイス リソースとシステム リソースを使用できる場合、ドライバーは I/O 操作を開始します。デバイスまたはリソースを使用できない場合、ドライバーは WdfIoQueueStop を呼び出して、現在の要求が処理されるまで追加の要求の送信を停止する必要があります。

必要に応じて、ドライバーは WdfIoQueueCreate を呼び出して各デバイスの追加キューを作成できます。その後、ドライバーは WdfRequestForwardToIoQueue を呼び出して、一部の種類の要求をこの追加キューに再登録できます。フレームワークが追加キューから要求を送信する場合、ドライバーは必要に応じて既定のキューではなくその追加キューで WdfIoQueueStop を呼び出すことで、送信が延期される要求の数または種類を最小限に抑えることができます。