タイマーの使用

このトピックは、フレームワークの組み込みタイマー サポートを使用する方法について説明します。 これは、カーネル モード ドライバー フレームワーク (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_CONFIGTolerableDelay メンバーを TolerableDelayUnlimited に設定します。

スリープ解除タイマーの詳細については、「スリープ解除タイマーなし」を参照してください。

高分解能タイマー

標準フレームワーク タイマーには、システム クロックのティック間隔 (既定では 15.6 ミリ秒) に一致する精度があります。 Windows 8.1 以降では、高解像度タイマーを作成できます。 高解像度タイマーの精度は 1 ミリ秒です。 正確で予測可能な有効期限を必要とする重要な操作には、高解像度タイマーを使用できます。 必要な頻繁なサービスの結果として、高解像度タイマーによってバッテリ寿命が低下する可能性があります。

高解像度タイマーは、KMDF バージョン 1.13 以降の KMDF ドライバーでのみ使用できます。

高解像度タイマーを作成するには、WDF_TIMER_CONFIGUseHighResolutionTimer メンバーを WdfTrue に設定し、Period 値を目的の解像度に調整します。

次の表に、ドライバーが Period に提供するさまざまな値に基づくタイマー動作の例を示します。 これらの例では、システム クロックのティック間隔が 15 ミリ秒であることを前提としています。

ピリオド (ミリ秒) 標準タイマー 高分解能タイマー

10

タイマーの有効期限は 0 ミリ秒から 25 ミリ秒です。

タイマーは、可能な限り 10 ミリ秒後にすぐに期限切れになります。

16

タイマーの有効期限は 15 ミリ秒から 30 ミリ秒です。

タイマーは、可能な限り 16 ミリ秒後にすぐに期限切れになります。

高解像度タイマーの詳細については、「高解像度タイマー」をご参照ください。

タイマーの精度とシステム クロックの粒度の関係の詳細については、「タイマーの精度」をご参照ください。