本页目录
时钟与定时器
覆盖: timer wheel → hrtimer (红黑树) → clockevent/clocksource → tick (periodic/dyntick/nohz) → POSIX timer → itimer 内核版本: 2.6 ~ 6.x
概述
内核中有两套定时器系统共存:
- timer wheel (低精度): jiffy 粒度 (1/HZ 秒, 通常 1ms/4ms),
mod_timer()/del_timer() - hrtimer (高精度): 纳秒级, 红黑树排序,
hrtimer_start()/hrtimer_cancel()
这一双轨设计源自历史:timer wheel 是原始实现,hrtimer 是 2.6.16 引入的精确替代。现在两者共存——timer wheel 处理低精度大量定时器(如网络超时),hrtimer 处理精确事件(如 POSIX timer、tick 模拟)。
Jiffies 与 HZ
// include/linux/jiffies.h
extern unsigned long volatile jiffies; // 自启动以来的 tick 数
// HZ = 每秒的 tick 数 (内核编译时配置):
// CONFIG_HZ=100 → 10ms 精度 (服务器, 低 CPU 开销)
// CONFIG_HZ=250 → 4ms 精度 (默认)
// CONFIG_HZ=1000 → 1ms 精度 (桌面/实时, 更平滑但更多中断)
// jiffies wrap:
// 32-bit: 2^32 / HZ ≈ 497 天 (HZ=100)
// 64-bit: wrap 大于宇宙寿命
// time_after(a, b) / time_before(a, b) 宏处理 wrap 比较
Timer Wheel: 低精度定时器
// kernel/time/timer.c
// 按到期时间分桶 (类似水钟)
// 桶大小: 1 jiffy, 8 jiffies, 64 jiffies, 512 jiffies, ...
;
// 注册:
; // 500ms 后触发
// 删除:
; // 同步删除
; // 等待可能正在运行的 handler 完成
// 定时器在 softirq 上下文运行 (TIMER_SOFTIRQ)
// → 不能睡眠, 不能拿 mutex
hrtimer: 高精度定时器
// kernel/time/hrtimer.c
// 纳秒级精度, 红黑树排序
// 需要硬件支持 (HPET, TSC, 或 APIC timer)
;
// 使用:
;
timer.function = my_callback;
;
// → 1ms 后回调
// hrtimer 到期 → 在中断上下文中回调 (HRTIMER_SOFTIRQ)
// 如果需要睡眠 → 使用 schedule_hrtimeout()
Clock Event 与 Clock Source
// kernel/time/clockevents.c + kernel/time/clocksource.c
// clocksource: 提供当前时间 (抽象了 TSC, HPET, ACPI PM timer)
// read() → 返回 cycle_t (monotonic counter)
// → 通过 mult/shift 转换为纳秒
// clockevent: 提供未来事件编程 (抽象了 Local APIC timer, HPET)
// set_next_event(delta_ns) → 编程硬件在 delta_ns 后产生中断
// → 这是 tick 和 hrtimer 的硬件基础
// tick device:
// 每个 CPU 有一个 clockevent 作为 tick device
// 可以是 per-CPU (Local APIC timer) 或全局 broadcast (HPET)
Tick 管理: periodic / dyntick / nohz
// 三种 tick 模式:
// 1. Periodic tick (旧):
// 每个 CPU 每 1/HZ 秒产生一次 timer interrupt
// → 用于更新时间 (jiffies), 调度器 tick, 进程统计
// → 但大部分 tick 是浪费的 (CPU idle 时不需要 tick)
// 2. Dynamic tick (dyntick / CONFIG_NO_HZ_IDLE, 2.6.21+):
// 当 CPU idle 时: 停止 tick → CPU 进入深度睡眠 (C-state)
// → 根据下一个定时器到期时间编程 clockevent 一次性唤醒
// → 节能: 每瓦特跑更多工作
// 3. Full nohz (CONFIG_NO_HZ_FULL, 3.10+):
// 当 CPU 只有一个可运行任务时: 停止 tick
// → 减少 tick 中断对延迟敏感任务 (HPC/实时) 的干扰
// → 但 RCU 和 sched 统计需要 adapt → 更复杂
POSIX Timer 与 itimer
// kernel/time/posix-timers.c
// 用户态定时器 API:
// POSIX timer (per-process):
;
;
// → 内核创建 hrtimer → 到期时发信号 (SIGALRM, SIGEV_SIGNAL)
// POSIX interval timer (itimer):
; // SIGALRM
; // SIGVTALRM (仅用户态时间)
; // SIGPROF (用户+内核时间)
// timerfd (2.6.25+):
int fd = ;
;
// → fd 可读 → 定时器到期 (可 poll/epoll, 极方便)
调试
# 当前 tick 模式
# timer wheel 统计 (/proc/timer_list)
|
# hrtimer 统计
|
# HZ 值
参考与延伸
- 内核文档:
Documentation/timers/ - LWN: "The timer wheel", "hrtimers and the tick", "NOHZ full"
- 源码:
kernel/time/timer.c— timer wheelkernel/time/hrtimer.c— hrtimerkernel/time/tick-common.c— tick 管理kernel/time/tick-sched.c— dyntick/nohzkernel/time/clocksource.c— clocksourcekernel/time/clockevents.c— clockeventkernel/time/posix-timers.c— POSIX timer
关键词: timer wheel, hrtimer, jiffies, HZ, clockevent, clocksource, dyntick, nohz, POSIX timer, timerfd