I/O 要求のキャンセル

デバイスの進行中の I/O 操作 (ディスクから複数のブロックを読み取る要求など) は、アプリケーション、システム、またはドライバーによって取り消されることがあります。 デバイスの I/O 操作が取り消されると、I/O マネージャーは、I/O 操作に関連付けられているすべての未処理の I/O 要求を取り消そうとします。 デバイスのドライバーは、I/O マネージャーが I/O 要求を取り消そうとしたときに通知を受け取るように登録できます。また、ドライバーは、完了状態が STATUS_CANCELLED で完了することによって、所有する要求を取り消すことができます。

フレームワークは、フレームワークベースのドライバーのキャンセル処理の一部を処理します。 デバイスの I/O 操作が取り消された場合、フレームワークは取り消された操作に関連付けられている後続の I/O 要求 (完了状態 STATUS_CANCELLED で) を完了します。

  • フレームワークがドライバーの既定の I/O キューに配置した未配信 I/O 要求。

  • ドライバーが WdfDeviceConfigureRequestDispatching を呼び出したため、フレームワークが別のキューに転送された未配信の I/O 要求。

フレームワークはこれらの要求を取り消すので、ドライバーには配信されません。

フレームワークがドライバーに I/O 要求を配信した後、ドライバーは要求を所有し、フレームワークはそれを取り消すことができません。 この時点で、ドライバーのみが I/O 要求を取り消すことができますが、フレームワークは要求を取り消す必要があることをドライバーに通知する必要があります。 ドライバーは、EvtRequestCancel コールバック関数を提供することで、この通知を受け取ります。

場合によっては、ドライバーは I/O キューから I/O 要求を受信しますが、要求を処理する代わりに、後で処理するために同じまたは別の I/O キューに要求を再度キューに入れます。 この状況の例としては、次のようなものがあります。

このような場合、要求が I/O キューにあるため、フレームワークは I/O 要求を取り消すことができます。 ただしドライバーが、要求が存在する I/O キューの EvtIoCanceledOnQueue コールバック関数を登録している場合、フレームワークは、関連付けられている I/O 操作が取り消されるときに、要求を取り消す代わりにコールバック関数を呼び出します。 フレームワークがドライバーの EvtIoCanceledOnQueue コールバック関数を呼び出す場合、ドライバーは要求を完了する必要があります。

要約すると、I/O 操作が取り消されると、フレームワークは常に、ドライバーに配信されなかった関連付けられているすべての I/O 要求を取り消します。 ドライバーが要求を受け取り、その要求を再度キューに入れた場合、ドライバーが I/O キューの EvtIoCanceledOnQueue コールバック関数を提供しない限り、フレームワークは要求を取り消します (要求がキューにある場合)。

WdfRequestMarkCancelable または WdfRequestMarkCancelableEx の呼び出し

ドライバーは、WdfRequestMarkCancelable または WdfRequestMarkCancelableEx を呼び出して、EvtRequestCancel コールバック関数を登録できます。 ドライバーが WdfRequestMarkCancelable または WdfRequestMarkCancelableEx を呼び出し、要求に関連付けられている I/O 操作が取り消された場合、フレームワークはドライバーの EvtRequestCancel コールバック関数を呼び出して、ドライバーが I/O 要求を取り消すことができるようにします。

ドライバーは、比較的長い間要求を所有する場合、WdfRequestMarkCancelable または WdfRequestMarkCancelableEx を呼び出す必要があります。 たとえば、ドライバーがデバイスの応答を待機する必要がある場合や、ドライバーが 1 つの要求を受信したときに作成された一連の要求を下位ドライバーが完了するまで待機する必要がある場合があります。

ドライバーが WdfRequestMarkCancelable または WdfRequestMarkCancelableEx を呼び出さない場合、またはドライバーが WdfRequestMarkCancelable または WdfRequestMarkCancelableEx を呼び出した後に WdfRequestUnmarkCancelable を呼び出した場合、ドライバーはキャンセルを認識しないため、通常と同様に要求を処理します。

WdfRequestIsCanceled の呼び出し

ドライバーが WdfRequestMarkCancelable または WdfRequestMarkCancelableEx を呼び出して EvtRequestCancel コールバック関数を登録していない場合は、WdfRequestIsCanceled を呼び出して、I/O マネージャーが I/O 要求を取り消そうとしたかどうかを判断できます。 WdfRequestIsCanceledTRUE を返し、ドライバーが要求を所有している場合、ドライバーは要求をキャンセルする必要があります。 ドライバーが要求を所有していない場合は、WdfRequestIsCanceled を呼び出さないでください。

WdfRequestMarkCancelable または WdfRequestMarkCancelableEx を呼び出していないドライバーは、次の状況で WdfRequestIsCanceled を呼び出す可能性があります。

  • デバイスの割り込みを待機するドライバーは、その EvtInterruptDpc コールバック関数から WdfRequestIsCanceled を呼び出す可能性があります。

  • デバイスをポーリングするドライバーは、ポーリング スレッドから WdfRequestIsCanceled を呼び出す可能性があります。

  • DMA トランザクションをいくつかの小さな転送に分割するドライバーは、各転送が完了した後に WdfRequestIsCanceled を呼び出す可能性があります。

  • ドライバーが受信した要求に対して WdfRequestMarkCancelable または WdfRequestMarkCancelableEx を呼び出していない場合、ドライバーが大きな読み取りまたは書き込み要求を受取り、それを複数の小さい要求に分割すると、ドライバーは I/O ターゲットが小さい各要求を完了した後に、WdfRequestIsCanceled を呼び出す可能性があります。

要求の取り消し

I/O 要求の取り消しには、次のいずれかが関係する場合があります。

  • 進行中の I/O 操作の停止。

  • 要求を I/O ターゲットに転送しない場合。

  • WdfRequestCancelSentRequest を呼び出して、ドライバーが以前に I/O ターゲットに送信した要求を取り消そうとする場合。

ドライバーがフレームワークから受信した要求オブジェクトの I/O 要求を取り消している場合、ドライバーは必ず、STATUS_CANCELLED の Status パラメーターを使用して、WdfRequestCompleteWdfRequestCompleteWithInformation、または WdfRequestCompleteWithPriorityBoost を呼び出して要求を完了する必要があります。 (ドライバーが、WdfRequestCreate を呼び出して要求オブジェクトを作成する場合、ドライバーは、要求を完了する代わりに WdfObjectDelete を呼び出します)。

取り消しの同期

I/O 要求を取り消すコードの同期については、次を参照してください。