CustomTimerDpc ルーチンの登録とキュー
ドライバは CustomTimerDpc ルーチンを登録することができますが、これは AddDevice ルーチンから以下のルーチンを呼び出すことで実施されます。
KeInitializeDpc で、そのルーチンを登録する
KeInitializeTimer または KeInitializeTimerEx でタイマー オブジェクトを設定する
その後、ドライバーは、KeSetTimer またはKeSetTimerEx を呼び出すと、有効期限を指定し、システムのタイマー キューにタイマー オブジェクトを追加することができます。 有効期限に達すると、システムはタイマー オブジェクトをデキューし、CustomTimerDpc ルーチンを呼び出します。 次の図は、これらの呼び出しを示します。
前の図にあるように、ドライバーでは DPC オブジェクトとタイマー オブジェクトの両方の記憶域を提供する必要があります。 ほとんどのドライバーが、デバイス拡張機能またはその他のドライバーによって割り当てられた常駐メモリ内のこれらのオブジェクトの記憶域を提供します。
前の図に示すように KeSetTimerの呼び出しでは、ドライバーは Dpc オブジェクトと Timer オブジェクトへのポインタを 100 ナノ秒単位で表される DueTime とともに渡されます。 DueTime の正の値は、CustomTimerDp ルーチンを呼び出す絶対有効期限 (1601 年 1 月 1 日以降) を指定します。 DueTime の負の値は、相対的な有効期限を指定します。
絶対タイマーは特定のシステム時刻に期限切れになるため、タイマーが期限切れになる前にシステム時刻を変更しても、絶対タイマーの待機時間に影響はありません。 一方、絶対システム時間の変更に関係なく、指定された時間単位数が経過すると、相対タイマーは常に期限切れになります。
CustomTimerDpc ルーチンを繰り返し呼び出すには、KeSetTimerEx を使用してタイマーを設定し、Period パラメーターで定期的な時間間隔を指定します。 KeSetTimerEx は、この追加パラメーター以外は、KeSetTimer と同じです。
前の図に示すように、KeSetTimer または KeSetTimerEx に対する呼び出しで、指定された時間間隔のタイマー オブジェクトは次のようにキューに入ります。
DueTime の有効期限が切れると、タイマー オブジェクトはデキューされ、Signaled 状態に設定されます。
マシン内のすべてのプロセッサで現在、DISPATCH_LEVEL 以上の IRQL でコードが実行されている場合、タイマー オブジェクトに関連付けられている DPC オブジェクトは DPC キューに入れられます。 それ以外の場合は 、CustomTimerDpc ルーチンが呼び出されます。
DueTime 間隔の有効期限が切れたときに DPC オブジェクトが既にキューに入っていた場合、コンピューター内の任意のプロセッサの IRQL が DISPATCH_LEVEL を下回るとすぐに CustomTimerDpc ルーチンが呼び出されます。
Note
CustomTimerDpc ルーチンは、すべての DPC ルーチンと同様に、IRQL = DISPATCH_LEVEL で呼び出されます。 DPC ルーチンの実行中は、すべてのスレッドは同じプロセッサで実行されません。 ドライバー開発者は、できるだけ短時間で実行されるように CustomTimerDpc ルーチンを慎重に設計する必要があります。
KeSetTimer と KeSetTimerEx iに指定できる最小の時間間隔は約10ミリ秒であるため、 CustomTimerDpc ルーチンを使用することで、ドライバは 1 秒に 1 回実行される IoTimer ルーチンが処理できるよりも小さな間隔に対応できます。
キューに入れることのできる特定のタイマー オブジェクトのインスタンス化は、いつでも 1 つだけです。 KeSetTimer または KeSetTimerEx を同じ Timer オブジェクトポインターで再度呼び出すと、キューにある Timer オブジェクトはキャンセルされ、リセットされます。
CustomTimerDpc ルーチンの設定手順は、タイマー オブジェクトを初期化する追加手順で CustomDpc ルーチンを設定する場合とまったく同じです。 実際、両者のプロトタイプは同じですが、CustomTimerDpc ルーチンでは、そのプロトタイプで宣言されている 2 つの SystemArgument ポインターを使用できません。