タイマーの使用
このトピックは、フレームワークの組み込みタイマー サポートを使用する方法について説明します。 これは、カーネル モード ドライバー フレームワーク (KMDF) ドライバーと、バージョン 2 以降のユーザー モード ドライバー フレームワーク (UMDF) ドライバーの両方に適用されます。
フレームワークには、ドライバーがタイマーを作成できるようにするタイマー オブジェクト が用意されています。 ドライバーがタイマー オブジェクトを作成し、タイマーのクロックを開始した後、フレームワークは、ドライバーが指定したコールバック関数を、指定した時間が経過した後に呼び出します。 必要に応じて、ドライバーは、指定した時間が経過するたびに、フレームワークがコールバック関数を繰り返し呼び出すタイマーを設定できます。
フレームワーク タイマー オブジェクトを作成するには、ドライバーが WdfTimerCreate メソッドを呼び出す必要があります。 このメソッドは EvtTimerFunc コールバック関数と定期的な時間間隔を登録します。 フレームワークでコールバック関数を 1 回だけ呼び出す場合、ドライバーは定期的な時間間隔に 0 を指定します。
通常、ドライバーが各デバイスに必要とするタイマーの数がわかります。 そのため、ドライバーは、EvtDriverDeviceAdd コールバック関数で WdfTimerCreate を呼び出すことによってタイマー オブジェクトを作成でき、タイマー オブジェクト ハンドルをデバイスまたはキュー オブジェクトのコンテキスト空間に格納できます。
タイマーを開始するには、ドライバーで WdfTimerStart を呼び出し、「期限」 を渡します。 フレームワークは、タイマーのクロックを開始し、指定した時間が経過したときに EvtTimerFunc コールバック関数を呼び出します。
ドライバーが WdfTimerCreate を呼び出したときに定期的な時間間隔を指定した場合、タイマーは定期的なタイマーと呼ばれます。 定期的なタイマーのクロックは、最初の 「期限」 が経過した後も引き続き実行され、フレームワークは、定期的な時間間隔が経過するたびに、ドライバーのコールバック関数を繰り返し呼び出します。 定期的なタイマーは自動的に開始されません。 非定期的なタイマーと同様に、ドライバーは、初めて開始するタイマーを作成した後も WdfTimerStart を呼び出す必要があります。
ドライバーは、有効期限が切れた後に非定期的なタイマーを再起動するために、その EvtTimerFunc コールバック関数から WdfTimerStart を呼び出す可能性があります。
タイマーを停止するために、ドライバーは WdfTimerStop を呼び出すことができます。 ドライバーは、タイマーを繰り返し開始および停止することで再利用できます。
ドライバーは、タイマー オブジェクトを作成するときに、親オブジェクトを指定する必要があります。 フレームワークはタイマーを停止し、親が削除されたときにタイマー オブジェクトを削除します。 タイマー オブジェクトの親オブジェクトを取得するには、ドライバーは WdfTimerGetParentObject を呼び出すことができます。
バージョン 1.9 より前の KMDF バージョンでは、IRQL = PASSIVE_LEVEL ですべてのドライバーのコールバック関数を実行する場合、タイマー オブジェクトを簡単に使用することはできません。 このフレームワークは、タイマー オブジェクトの EvtTimerFunc コールバック関数を、IRQL = DISPATCH_LEVEL で呼び出される遅延プロシージャ 呼び出し (DPC) として実装します。 したがって、タイマーの有効期限コードをPASSIVE_LEVELに実行する場合、EvtTimerFunc コールバック関数は、PASSIVE_LEVELで実行される作業項目をキューに入れる必要があります。
KMDF バージョン 1.9 以降では、パッシブ レベルのタイマーである、(PASSIVE_LEVELで実行されるタイマー)を作成できます。 パッシブ レベルのタイマーを作成するには、ドライバーが WdfTimerCreate を呼び出すときに WdfExecutionLevelPassive 実行レベルを指定します。 その結果、フレームワークは、PASSIVE_LEVELで実行される作業項目として EvtTimerFunc コールバック関数を実装します。 パッシブ レベルのタイマーを定期的なタイマーにすることはできません。
UMDF バージョン 2.0 以降、フレームワークはタイマー オブジェクトの EvtTimerFunc コールバック関数をユーザー モード スレッド プールのワーカー スレッドとして実装します。 その結果、UMDF ドライバーのタイマー コールバック関数は常にPASSIVE_LEVELで実行されます。
ウェイクなしタイマー
システムの電力効率は、システムが低電力状態から再開するタイマーによって繰り返し低下します。 バッテリ寿命を向上させる 1 つの方法は、システムをスリープ解除するのではなく、重要でない定期的な操作を遅延することです。 Windows 8.1 以降では、KMDF ドライバーまたは UMDF ドライバーでこのような重要でない操作を実行するために、ウェイク タイマーを使用できません。 システムが低電力状態の間に期限切れになった場合、スリープ解除タイマーはシステムをスリープ解除しません。 代わりに、フレームワークは、ドライバーの EvtTimerFunc コールバック関数、システムが完全にオン、S0 状態の次回を呼び出します。
KMDF バージョン 1.13 および UMDF バージョン 2.0 以降では、ウェイク タイマーは使用できません。
スリープ解除タイマーを作成するには、WDF_TIMER_CONFIG の TolerableDelay メンバーを TolerableDelayUnlimited に設定します。
スリープ解除タイマーの詳細については、「スリープ解除タイマーなし」を参照してください。
高分解能タイマー
標準フレームワーク タイマーには、システム クロックのティック間隔 (既定では 15.6 ミリ秒) に一致する精度があります。 Windows 8.1 以降では、高解像度タイマーを作成できます。 高解像度タイマーの精度は 1 ミリ秒です。 正確で予測可能な有効期限を必要とする重要な操作には、高解像度タイマーを使用できます。 必要な頻繁なサービスの結果として、高解像度タイマーによってバッテリ寿命が低下する可能性があります。
高解像度タイマーは、KMDF バージョン 1.13 以降の KMDF ドライバーでのみ使用できます。
高解像度タイマーを作成するには、WDF_TIMER_CONFIG の UseHighResolutionTimer メンバーを WdfTrue に設定し、Period 値を目的の解像度に調整します。
次の表に、ドライバーが Period に提供するさまざまな値に基づくタイマー動作の例を示します。 これらの例では、システム クロックのティック間隔が 15 ミリ秒であることを前提としています。
ピリオド (ミリ秒) | 標準タイマー | 高分解能タイマー |
---|---|---|
10 |
タイマーの有効期限は 0 ミリ秒から 25 ミリ秒です。 |
タイマーは、可能な限り 10 ミリ秒後にすぐに期限切れになります。 |
16 |
タイマーの有効期限は 15 ミリ秒から 30 ミリ秒です。 |
タイマーは、可能な限り 16 ミリ秒後にすぐに期限切れになります。 |
高解像度タイマーの詳細については、「高解像度タイマー」をご参照ください。
タイマーの精度とシステム クロックの粒度の関係の詳細については、「タイマーの精度」をご参照ください。