I/O キューの使用例

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

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

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

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

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

たとえば、次のようなシナリオが考えられます。

1 つのシーケンシャル I/O キュー

読み取り要求と書き込み要求を一度に 1 つしか処理できないディスク ドライブのファンクション ドライバーを作成する場合、ファンクション ドライバーはデバイスごとに 1 つの I/O キューのみを必要とします。

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

  • 既定の I/O キューがドライバーに I/O 要求を同期的に配信するための、ディスパッチ メソッドとしての WdfIoQueueDispatchSequential

  • すべての I/O 要求を受信する 1 つのイベント コールバック関数 EvtIoDefault

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

複数のシーケンシャル I/O キューと手動キュー

次の特性を持つシリアル ポート デバイスについて考えてみましょう。

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

  • 複数の読み取り操作または書き込み操作を非同期的に実行することはできません。

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

このデバイスのファンクション ドライバーでは、デバイスごとに複数のシーケンシャル I/O キューを使用できます。 ドライバーは WdfIoQueueCreate を 3 回呼び出します。1 回は既定のキューを作成し、2 回は追加の I/O キューを作成するためです。 これらの各キューの WDF_IO_QUEUE_CONFIG 構造では、ドライバーで次を指定する必要があります。

  • フレームワークがドライバーに I/O 要求を同期的に配信できるようにするための、各キューのディスパッチ メソッドとしての WdfIoQueueDispatchSequential

  • キュー (EvtIoDefaultEvtIoReadEvtIoWrite) ごとに異なる要求ハンドラー。キューの I/O 要求を受信します。

WdfIoQueueCreate を呼び出した後、ドライバーは WdfDeviceConfigureRequestDispatching を 2 回呼び出して、すべての読み取り要求をいずれかの追加キューに転送し、すべての書き込み要求を他方のキューに転送できます。

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

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

1 つの並列 I/O キュー

IDE ディスク コントローラーは、一部の I/O 操作が重複する可能性がありますが、他の I/O 操作は重複しません。 たとえば、コントローラーが 1 つのディスクで読み取りまたは書き込み操作を処理している間に、seek コマンドを別のディスクに送信できます。 一方、複数の同時読み取りおよび書き込みコマンドはサポートされていません。

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

  • 指定されたディスク ドライブは既にビジー状態。

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

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

  • フレームワークがドライバーに I/O 要求を非同期的に配信できるようにするための、各キューのディスパッチ メソッドとしての WdfIoQueueDispatchParallel

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

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

複数の並列 I/O キュー

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

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

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

パフォーマンスを最大限に高めるには、この SCSI ホスト アダプターのファンクション ドライバーは、使用可能になるとすぐにフレームワークから I/O 要求を受け取る必要があります。 ドライバーは、各要求を調べて、すぐに開始できるか、またはデバイスとリソース (メールボックス メモリなど) が使用可能になるまで延期する必要があるかどうかを判断する必要があります。

ドライバーは、おそらく複数の並列 I/O キューを使用する必要があります。 コントローラーに接続されている各アダプターについて、ドライバーは WdfIoQueueCreate を呼び出して既定の I/O キューを作成します。 これらの各キューの WDF_IO_QUEUE_CONFIG 構造では、ドライバーで次を指定する必要があります。

  • フレームワークがドライバーに I/O 要求を非同期的に配信できるようにするための、各キューのディスパッチ メソッドとしての WdfIoQueueDispatchParallel

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

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

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