Linux Kernel/高精度定时器

按精确到期时间组织高精度定时器

hrtimer 通过 timerqueue 的红黑树维护到期顺序,并缓存最早到期节点。

v6.12调度与资源分配核验 2026-10-11
相关概念

工程问题#

高精度定时器需要频繁插入、取消和确定下次唤醒时刻;超时值分布不一定落在规则的粗粒度时间槽中。

实际实现#

enqueue_hrtimer 将节点交给 timerqueue_add;后者调用 rb_add_cached。树按 expires 比较,缓存最左节点便于读取下一到期项。

处理流程#

  1. 选择对应时钟和 CPU 的 timer base
  2. 按 expires 插入红黑树
  3. 读取最早到期事件
  4. 到期出队后执行回调或重新入队

源码片段#

固定版本 · 原文摘录
lib/timerqueue.cv6.12 · L20–L41
查看原文件
20static inline bool __timerqueue_less(struct rb_node *a, const struct rb_node *b)21{22	return __node_2_tq(a)->expires < __node_2_tq(b)->expires;23}2425/**26 * timerqueue_add - Adds timer to timerqueue.27 *28 * @head: head of timerqueue29 * @node: timer node to be added30 *31 * Adds the timer node to the timerqueue, sorted by the node's expires32 * value. Returns true if the newly added timer is the first expiring timer in33 * the queue.34 */35bool timerqueue_add(struct timerqueue_head *head, struct timerqueue_node *node)36{37	/* Make sure we don't add nodes that are already added */38	WARN_ON_ONCE(!RB_EMPTY_NODE(&node->node));3940	return rb_add_cached(&node->node, &head->rb_root, __timerqueue_less);41}
__timerqueue_less; timerqueue_add

比较函数以 expires 建立到期顺序,rb_add_cached 插入节点并维护最左缓存。hrtimer 的 enqueue_hrtimer 在 kernel/time/hrtimer.c 调用此库函数;返回值说明新节点是否成为最早到期节点。

kernel/time/hrtimer.cv6.12 · L1073–L1094
查看原文件
1073/*1074 * enqueue_hrtimer - internal function to (re)start a timer1075 *1076 * The timer is inserted in expiry order. Insertion into the1077 * red black tree is O(log(n)). Must hold the base lock.1078 *1079 * Returns 1 when the new timer is the leftmost timer in the tree.1080 */1081static int enqueue_hrtimer(struct hrtimer *timer,1082			   struct hrtimer_clock_base *base,1083			   enum hrtimer_mode mode)1084{1085	debug_activate(timer, mode);1086	WARN_ON_ONCE(!base->cpu_base->online);10871088	base->cpu_base->active_bases |= 1 << base->index;10891090	/* Pairs with the lockless read in hrtimer_is_queued() */1091	WRITE_ONCE(timer->state, HRTIMER_STATE_ENQUEUED);10921093	return timerqueue_add(&base->active, &timer->node);1094}
enqueue_hrtimer

完整 hrtimer 入队函数与复杂度注释:调用者必须持有 base 锁,状态更新后把节点加入 timerqueue。与已有 lib/timerqueue.c 片段共同证明 hrtimer 的真实调用关系。

两个连续片段分别展示 timerqueue 库和实际 hrtimer 调用方。库本身不加锁,enqueue_hrtimer 要求调用者持有 base 锁;片段不展示时钟事件编程与回调执行。

收益与取舍#

工程分析

带来的收益

  • 保留完整的到期顺序
  • 缓存最小节点减少重复遍历

付出的代价

  • 工程分析:插入删除需要维护树平衡
  • 精确队列不能消除中断与执行延迟

可比较的选择

Linux 普通时间轮以较粗时间槽组织大量通常会被取消的普通超时,固定层数下选槽和挂入成本不随定时器数增长;v6.12 不再采用经典级联迁移。

QEMU 有序定时器链表QEMU v9.2.0 的相应实现读取表头直接,插入按到期时间线性扫描 O(n);与红黑树不同,适用取舍需结合各自定时器数量与运行环境。

版本与适用范围#

固定 Linux v6.12 的 hrtimer 子系统。它按到期时间维护红黑树,并缓存最左节点;普通 timer_list 则使用非级联多层时间轮。纳秒单位表示不等于每次回调都有纳秒级的实际精度,实际触发还受时钟事件设备、CPU 状态与调度影响。

参考来源#

源码、官方文档与原始论文
01
linux · enqueue_hrtimer

kernel/time/hrtimer.c · enqueue_hrtimer

源码v6.12
02
linux · timerqueue_add / timerqueue_del

lib/timerqueue.c · timerqueue_add / timerqueue_del

源码v6.12

相关实现与比较#

4 个相关案例
nginx·事件循环release-1.26.3

nginx 事件定时器以到期时间为键放入红黑树,事件循环读取最小键确定等待上限。

附源码片段 · 调度与资源分配
11 个匹配案例