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 キュー内にあるため、フレームワークが要求を取り消すことができます。ただし、要求が存在する 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 を呼び出す必要があります。たとえば、デバイスの応答を待機する必要がある場合、単一の要求を受信したときにそのドライバーが作成した一連の要求を下位のドライバーが完了するまで待機する場合などがあります。

ドライバーが WdfRequestMarkCancelable または WdfRequestMarkCancelableEx を呼び出さない場合、あるいは WdfRequestMarkCancelable または WdfRequestMarkCancelableEx を呼び出した後に WdfRequestUnmarkCancelable を呼び出す場合、ドライバーは要求の取り消しを認識できないため、通常どおりに要求を処理します。

WdfRequestIsCanceled の呼び出し

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

次のような場合、WdfRequestMarkCancelable または WdfRequestMarkCancelableEx を呼び出していないドライバーが WdfRequestIsCanceled を呼び出すことがあります。

  • デバイスの割り込みを待機するドライバーが、EvtInterruptDpc コールバック関数から WdfRequestIsCanceled を呼び出す場合。

  • デバイスに対してポーリングを行うドライバーが、ポーリング スレッドから WdfRequestIsCanceled を呼び出す場合。

  • DMA トランザクションを複数の小さな転送に分割するドライバーが、転送が終了するたびに WdfRequestIsCanceled を呼び出す場合。

  • 受信した大規模な読み込み要求または書き込み要求を複数の小さな要求に分割するドライバーが、ドライバーの I/O ターゲットで小さな要求の処理が終了するたびに WdfRequestIsCanceled を呼び出す場合 (ただし、受信した要求に対してドライバーが WdfRequestMarkCancelable または WdfRequestMarkCancelableEx を呼び出していない場合のみ)。

要求の取り消し

I/O 要求の取り消しには、次の任意の操作が必要になる場合があります。

  • 進行中の I/O 操作を中止する。

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

  • WdfRequestCancelSentRequest を呼び出して、ドライバーが前に I/O ターゲットに送信した要求の取り消しを試行する。

ドライバーは、フレームワークから受信した要求オブジェクトの I/O 要求を取り消す場合、常に、Status パラメーターを STATUS_CANCELLED に設定して WdfRequestCompleteWdfRequestCompleteWithInformation、または WdfRequestCompleteWithPriorityBoost を呼び出すことによって、要求を完了させる必要があります。ドライバーが WdfRequestCreate を呼び出して要求オブジェクトを作成した場合、そのドライバーは要求を完了させる代わりに WdfObjectDelete を呼び出します。

取り消しの同期化

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

取り消しと完了のコードの同期化

送信済み要求の取り消しの同期化