TL

高分解能タイマとカーネルの時間管理

カーネルが時刻とタイマをどう作るかが分かれば、遅延やドリフトの原因を原理から切り分けられます。jiffiesからhrtimer、NO_HZ、単調時計とウォール時計の差まで一気に押さえられます。

応用タイマhrtimerNO_HZclocksourceLinuxカーネル最終更新: 2026-06-21
TL;DR要点だけ先に
  • 1.jiffiesはタイマ割り込み(tick)の回数を数えた低分解能の時間軸で、HZが250なら粒度は4ミリ秒。hrtimerはこれと独立にナノ秒粒度の期限を扱う。
  • 2.tickless(NO_HZ)はアイドルや単一実行時に周期tickを止め、消費電力とジッタを下げる。時刻はclocksourceから読み直すので時間は止まらない。
  • 3.clocksourceは時刻を読む源、clockeventは将来の割り込みを鳴らす器。単調時計は巻き戻らず、ウォール時計はNTPやうるう秒で飛ぶため計測には単調時計を使う。

カーネルが扱う「時間」は一種類ではない

カーネルにとって時間は単一の概念ではありません。少なくとも三つの役割があります。(1) 経過時間を数える時間軸、(2) 「いつ何かを起こすか」という期限の管理、(3) 「今が何時か」という時刻の提供です。これらを別々の仕組みで実現し、組み合わせているのが Linux の時間管理です。役割を混同すると、なぜ計測値がときどき巻き戻るのか、なぜ低負荷でも電力が下がらないのか、といった現象を読み解けません。

この記事で扱う4つの軸

jiffies(tick で数える粗い時間軸)、hrtimer(ナノ秒粒度の期限)、tickless(周期 tick を止める省電力)、clocksource/clockevent(読む源と鳴らす器の分離)。最後に単調時計とウォール時計の差を押さえます。すべて「時間を数える/鳴らす/読む」の三役のどこに属するかで整理できます。

jiffies と tick ── 粗いが安価な時間軸

最も古典的な時間軸が jiffies です。これはカーネル起動からのタイマ割り込み(tick)の累積回数を数えた単純なカウンタです。tick の頻度はビルド時定数 HZ で決まり、HZ が 250 なら 1 秒あたり 250 回、すなわち 1 jiffy = 4 ミリ秒です。

1 jiffy = 1 / HZ 秒
  HZ=100  → 10 ms 粒度(旧来サーバー向け)
  HZ=250  → 4 ms 粒度(汎用デスクトップの既定)
  HZ=1000 → 1 ms 粒度(低遅延寄り)

経過判定は引き算ではなく time_after()/time_before() マクロで行う
(jiffies は wrap するため符号付き差分で比較する)

tick は周期割り込みとして到来し、その都度カーネルは時刻の更新、タイムスライスの消費、各種タイマの満了チェックといった定常作業をまとめて処理します。jiffies の利点は 読み出しが極めて安価(メモリ上のカウンタを読むだけ)なことです。欠点は 粒度が tick まかせ で、HZ=250 なら 4 ミリ秒より細かい期限は表現できない点です。長く眠るタイマ(タイムアウトなど精度が要らない用途)には今でも timer_list(バケット分割した timer wheel という仕組みで管理される)が使われ、これは jiffies 基準で動きます。

hrtimer ── ナノ秒粒度の期限を別系統で

ミリ秒粒度では足りない用途——オーディオの再生間隔、nanosleepSCHED_DEADLINE の予算管理など——のために、jiffies とは独立した hrtimer(高分解能タイマ) があります。hrtimer は満了時刻を ナノ秒の絶対時刻 で保持し、tick の周期に縛られません。

仕組みの要は「期限ごとに割り込みを鳴らす」ことです。tick のように一定間隔で割り込むのではなく、次に満了する hrtimer の時刻に合わせて、ハードウェアタイマへ一発の割り込みを予約 します(後述の clockevent をワンショットモードで使う)。満了したらコールバックを呼び、次の最早期限へ向けて割り込みを再予約します。期限は赤黒木で時刻順に並べられ、挿入・削除は O(log n)、最左端(最も早い期限)はキャッシュされたポインタで O(1) に参照できます。常に必要なのはこの最早期限なので、割り込み予約は安価です。

観点timer_list(jiffies系)hrtimer(高分解能)
分解能1 jiffy(HZ依存、ms級)クロックソース依存(ns級)
時間軸の基準jiffies(tick回数)絶対ナノ秒時刻
割り込み形態周期tickに相乗り期限ごとにワンショット予約
向く用途精度が要らないタイムアウト精密な周期・期限・sleep
高分解能=常に高精度ではない

hrtimer がナノ秒粒度を「表現できる」ことと、その精度が「保証される」ことは別です。実際の精度は土台の clocksource の分解能、割り込み応答の遅れ、そしてカーネルが横取りできるかに左右されます。プリエンプション設計が緩いと、満了時刻を過ぎても CPU を得られず遅延が乗ります。最悪レイテンシの議論は /os/kernel-preemption/ と地続きで、/os/realtime-scheduling/ の締め切り保証もこの精度の上に成り立ちます。

clocksource と clockevent ── 読む源と鳴らす器の分離

ここまで「時刻を読む」「割り込みを鳴らす」と書いてきました。Linux はこの二つを 別の抽象 として明確に分離します。これが時間管理の設計の核です。

  • clocksource(クロックソース): 単調増加するカウンタを提供し、「今の時刻」を読むための源。TSC、HPET、ACPI PM タイマ、アーキテクチャ固有カウンタなどがこれを実装します。read() でカウンタ値を返し、カーネルが周波数とオフセットからナノ秒へ換算します。役割は 読む
  • clockevent(クロックイベント): 「指定した未来の時刻に割り込みを発生させる」器。周期モードとワンショットモードを持ち、tick も hrtimer もこれを使って割り込みを鳴らします。役割は 鳴らす
時刻を知りたい            →  clocksource.read() を読み、ns へ換算
将来の一点で起こしたい    →  clockevent をワンショット設定
一定周期で起こしたい      →  clockevent を周期設定(従来の tick)

clocksource と clockevent は同じ物理タイマでも別チップでもよい。
カーネルは精度・安定性で最良の clocksource を実行時に選ぶ。

分離の利点は、ハードウェアごとの差をこの二層で吸収し、上位の jiffies/hrtimer/時刻 API を共通化できることです。たとえば TSC が周波数可変や CPU 間ずれで信頼できない環境では、カーネルが clocksource を HPET へ切り替えても上位は無変更で動きます。この一発予約の割り込みは /os/interrupt-io/ のハンドラとして配送され、満了処理が走ります。

tickless(NO_HZ)── 周期 tick を止める

周期 tick には弱点があります。CPU が暇でも、あるいは 1 個のタスクしか走っていなくても、HZ 回/秒の割り込みが律儀に入り続けることです。これは省電力を妨げ(アイドルから何度も起こされる)、計算専用コアではジッタの原因にもなります。そこで導入されたのが tickless(NO_HZ) です。

モードtickを止める条件狙い
NO_HZ_IDLECPUがアイドルの間深いスリープを維持し消費電力を下げる
NO_HZ_FULL実行可能タスクが1個以下の間計算専用コアのジッタ・割り込みを除く
(periodic)止めない(常にHZ回)従来挙動・互換重視

ここで重要な原理があります。tick を止めても時間は止まりません。 周期割り込みで jiffies を逐次インクリメントする代わりに、tick を再開するとき clocksource を読んで「眠っていた間に何 jiffy 進んだか」をまとめて補正します。時刻そのものは clocksource という連続カウンタが握っているので、割り込みを間引いても失われないのです。tick を止める直前には「次に満了する hrtimer はいつか」を確認し、その時刻まで割り込みを予約してから眠ります。

NO_HZ_FULL の実務的な落とし穴

計算専用コアを作るには、NO_HZ_FULL の指定(isolcpus 等でのコア隔離)だけでなく、そのコアに割り込みを飛ばさない設定(IRQ affinity の調整)が要ります。割り込みの配送先を別コアへ寄せる話は /os/interrupt-top-bottom-half/ のアフィニティと同じ考え方です。tick を止めても他の割り込みが残れば、目当てのジッタ削減は得られません。

単調時計とウォール時計 ── 巻き戻る時間と巻き戻らない時間

最後に、提供される「時刻」が一種類でない点を押さえます。代表的な二つを区別します。

  • ウォール時計(CLOCK_REALTIME): 人間が読む壁掛け時計の時刻。1970年からの経過秒(UNIX 時刻)で表され、gettimeofday 等が返すもの。これは NTP による補正、管理者の手動変更、うるう秒 で前後に飛びます。つまり 巻き戻りうる
  • 単調時計(CLOCK_MONOTONIC): ある起点からの経過時間で、決して巻き戻らず後退しない。NTP は刻みの速度を微調整(slew)はしますが、時刻を飛ばすことはありません。区間計測やタイムアウトはこれを使います。
経過時間を測りたい・タイムアウトを置きたい
  → CLOCK_MONOTONIC(巻き戻らない/飛ばない)

「今が何時か」を人間向けに出したい・ログのタイムスタンプ
  → CLOCK_REALTIME(NTP・うるう秒で飛びうる)

派生:
  CLOCK_MONOTONIC_RAW  … NTPのslew補正すら掛けない生カウンタ
  CLOCK_BOOTTIME       … サスペンド中の時間も加算した単調時計
計測にウォール時計を使ってはいけない

区間計測を CLOCK_REALTIME で行うと、計測中に NTP 補正や時刻変更が入った瞬間、差分が負になったり巨大値になったりします。「処理時間がときどきマイナスになる」「稀に数十年の経過が記録される」障害の典型原因がこれです。経過時間・タイムアウト・リトライ間隔の計測は必ず CLOCK_MONOTONIC を使ってください。両者は同じ clocksource を土台にしつつ、ウォール時計だけにオフセット補正が乗る、と理解すると差が腑に落ちます。

両者の関係は単純です。カーネルは clocksource から得た単調なナノ秒値を基準に持ち、それへ「現在の壁時計オフセット」を足したものをウォール時計として提供します。NTP やうるう秒はこのオフセットを動かすだけで、単調側の連続性には触れません。だから一方は飛び、もう一方は飛ばないのです。

まとめ

  • 時間管理は 数える(jiffies)/鳴らす(clockevent)/読む(clocksource) の三役に分解できる。jiffies は tick 回数を数える安価だが粗い軸、hrtimer はそれと独立したナノ秒粒度の期限。
  • clocksource は時刻を読む源、clockevent は将来の割り込みを鳴らす器 で、両者の分離がハードウェア差の吸収と上位 API の共通化を可能にする。hrtimer は clockevent のワンショットで動く。
  • tickless(NO_HZ) は周期 tick を止めて省電力とジッタ削減を図るが、時刻は連続カウンタの clocksource が握るので止まらない。NO_HZ_FULL は割り込みアフィニティの併用が前提。
  • 単調時計は巻き戻らず、ウォール時計は NTP・うるう秒で飛ぶ。 区間計測・タイムアウトには必ず CLOCK_MONOTONIC を使う。
  • 高分解能タイマの実精度はプリエンプション設計に依存する。応答レイテンシは /os/kernel-preemption/、締め切り保証は /os/realtime-scheduling/ も参照。

OS Article

高分解能タイマとカーネルの時間管理を実務で読む

TL;DRは入口です。実際に選ぶ・使う段階では、何を解決するか、何と比較するか、導入後にどこで詰まるかまで見る必要があります。

解決すること

タイマ

比較で見る軸

難易度: advanced / カテゴリ: OS / タグ数: 6

導入後に効く点

tickless(NO_HZ)はアイドルや単一実行時に周期tickを止め、消費電力とジッタを下げる。時刻はclocksourceから読み直すので時間は止まらない。

先に潰すリスク

用語だけ覚えても、設計・実装・運用でどこに効くかを確認しないと判断を誤る。

数字・仕様の読み方
難易度
advanced
カテゴリ
OS
タグ数
6

判断チェックリスト

  • 自社の用途が「タイマ / hrtimer」に近いか確認する。
  • 強みである「jiffiesはタイマ割り込み(tick)の回数を数えた低分解能の時間軸で、HZが250なら粒度は4ミリ秒。hrtimerはこれと独立にナノ秒粒度の期限を扱う。」が本当に評価軸になるか確認する。
  • 注意点の「用語だけ覚えても、設計・実装・運用でどこに効くかを確認しないと判断を誤る。」を運用で吸収できるか確認する。
  • 公開値や仕様値は、対象プラン・対象機種・対象リージョンまで確認する。
  • 既存システム、ID、ネットワーク、監視、バックアップとの接続方法を先に洗い出す。
  • 小さく試してから、本番移行、権限設計、障害時手順、コスト監視を決める。

次に確認する観点

タイマhrtimerNO_HZclocksourceLinuxタイマhrtimerNO_HZ
参考: 公式情報