非同期プロシージャ呼び出し

非同期プロシージャ 呼び出し (APC) は、特定のスレッドのコンテキストで非同期的に実行される関数です。 APC がスレッドにキューに登録されると、システムはソフトウェア割り込みを発行します。 次回スレッドがスケジュールされると、APC 関数が実行されます。 システムによって生成された APC は、 カーネル モード APC と呼ばれます。 アプリケーションによって生成された APC は、 ユーザー モード APC と呼ばれます。 ユーザー モード APC を実行するには、スレッドがアラート可能な状態である必要があります。

各スレッドには、独自の APC キューがあります。 アプリケーションは、 QueueUserAPC 関数を呼び出してスレッドに APC をキューに入れます。 呼び出し元のスレッドは、 QueueUserAPC の呼び出しで APC 関数のアドレスを指定します。 APC のキューは、スレッドが APC 関数を呼び出す要求です。

ユーザー モード APC がキューに登録されている場合、APC 関数がアラート可能な状態でない限り、キューに入れられるスレッドは APC 関数を呼び出すように指示されません。 スレッドは、 SleepExSignalObjectAndWaitMsgWaitForMultipleObjectsExWaitForMultipleObjectsEx、または WaitForSingleObjectEx 関数を 呼び出すと、アラート可能な状態になります。 APC がキューに入れられる前に待機が満たされた場合、スレッドはアラート可能な待機状態ではなくなったため、APC 関数は実行されません。 ただし、APC はまだキューに登録されているため、スレッドが別のアラート可能な待機関数を呼び出すと、APC 関数が実行されます。

ReadFileExSetWaitableTimerSetWaitableTimerEx、および WriteFileEx 関数は、完了通知コールバック メカニズムとして APC を使用して実装されます。

スレッド プールを使用している場合は、システムによって スレッド プール スレッドの有効期間が制御されるため、通知が配信される前にスレッドが終了する可能性があるため、APC は他のシグナリング メカニズムと同様に機能しないことに注意してください。 SetWaitableTimer または SetWaitableTimerExpfnCompletionRoutine パラメーターなどの APC ベースのシグナリング メカニズムを使用する代わりに、CreateThreadpoolTimer で作成されたタイマーなどの待機可能オブジェクトを使用します。 I/O の場合は、CreateThreadpoolIo で作成された I/O 完了オブジェクト、またはイベントを SetThreadpoolWait 関数に渡すことができる hEvent ベースの OVERLAPPED 構造体を使用します。

同期内部

I/O 要求が発行されると、要求を表す構造体が割り当てられます。 この構造体は、I/O 要求パケット (IRP) と呼ばれます。 同期 I/O では、スレッドは IRP をビルドし、デバイス スタックに送信し、IRP が完了するまでカーネルで待機します。 非同期 I/O では、スレッドによって IRP がビルドされ、デバイス スタックに送信されます。 スタックは、IRP をすぐに完了するか、要求が進行中であることを示す保留中の状態を返す可能性があります。 この場合でも IRP はスレッドに関連付けられているため、スレッドが終了するか 、CancelIo などの関数を呼び出すと取り消されます。 それまでは、デバイス スタックが IRP の処理を続けている間、スレッドは引き続き他のタスクを実行できます。

システムが IRP が完了したことを示すことができるいくつかの方法があります。

  • スレッドがポーリングして操作が完了したかどうかを判断できるように、操作の結果と重複する構造体を更新します。
  • 重複した構造体でイベントを通知して、スレッドがイベントで同期し、操作の完了時に目を開くことができるようにします。
  • IRP をスレッドの保留中の APC にキューに入れ、スレッドがアラート可能な待機状態になったときに APC ルーチンを実行し、1 つ以上の APC ルーチンを実行したことを示す状態で待機操作から戻るようにします。
  • IRP を I/O 完了ポートにキューに入れます。このポートは、完了ポートで待機する次のスレッドによって実行されます。

I/O 完了ポートで待機するスレッドは、アラート可能な状態では待機しません。 したがって、これらのスレッドが、APC として完了するように設定された IRP をスレッドに発行した場合、それらの IPC 完了はタイムリーには発生しません。これらは、スレッドが I/O 完了ポートから要求を取得し、アラート可能な待機に入った場合にのみ発生します。

非同期プロシージャ呼び出しでの待機可能タイマーの使用