土法炼钢兴趣小组的算法知识备份

【操作系统百科】定时器

文章导航

分类入口
os
标签入口
#hrtimer#timer-wheel#tick#clock-event#jiffies

目录

内核需要”过一会儿做某事”——TCP 重传、watchdog、调度器时间片。定时器是底层时间机制的核心。

一、先看图

flowchart TD
    subgraph 低精度
        WHEEL[Timer Wheel<br/>层次哈希<br/>jiffies 精度]
    end
    subgraph 高精度
        HRTIMER[hrtimer<br/>红黑树<br/>纳秒精度]
    end
    WHEEL --> JIFFIES[基于 jiffies<br/>毫秒级]
    HRTIMER --> CLOCKEV[clock_event_device<br/>硬件定时器]

    classDef low fill:#f0883e22,stroke:#f0883e,color:#adbac7;
    classDef high fill:#3fb95022,stroke:#3fb950,color:#adbac7;
    class WHEEL,JIFFIES low
    class HRTIMER,CLOCKEV high

二、Timer Wheel(低精度)

2.1 层次结构

struct timer_list {
    struct hlist_node entry;
    unsigned long expires;     // jiffies
    void (*function)(struct timer_list *);
};

分层 wheel:

越远的定时器放在越粗的层 → 到期时再细化。

2.2 使用

struct timer_list timer;
timer_setup(&timer, callback, 0);
mod_timer(&timer, jiffies + msecs_to_jiffies(100));
del_timer_sync(&timer);

2.3 精度

jiffies 精度 = HZ 配置(100/250/1000 Hz)→ 1-10ms。

三、hrtimer(高精度)

3.1 数据结构

struct hrtimer {
    struct timerqueue_node node;   // 红黑树节点
    ktime_t _softexpires;          // 最早到期时间
    enum hrtimer_restart (*function)(struct hrtimer *);
};

3.2 使用

struct hrtimer timer;
hrtimer_init(&timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
timer.function = callback;
hrtimer_start(&timer, ktime_set(0, 100000), HRTIMER_MODE_REL);  // 100μs

3.3 精度

取决于硬件(TSC、LAPIC timer、ARM generic timer)→ 纳秒级。

四、clock_event_device

硬件定时器的抽象:

struct clock_event_device {
    void (*event_handler)(struct clock_event_device *);
    int (*set_next_event)(unsigned long, struct clock_event_device *);
    // ...
};

hrtimer 编程下一个到期时间到 clock_event_device → 硬件在到期时触发中断。

五、tick 与无 tick

5.1 周期 tick

每 HZ 次/秒产生 tick 中断 → 更新 jiffies、检查定时器、调度。

5.2 动态 tick(NO_HZ_IDLE)

空闲时跳过 tick → 省电。

5.3 全无 tick(NO_HZ_FULL)

运行中也跳过 tick → 减少干扰。

六、Slack 与 Coalescing

timer_setup(&timer, callback, 0);
timer.slack = msecs_to_jiffies(50);  // 允许 50ms 偏差

内核合并临近的定时器到期 → 减少唤醒次数 → 省电。

/proc/timer_stats(已废弃)→ perf tracepoints 替代。

七、定时器迁移

CPU 即将下线 → 迁移该 CPU 的定时器到其他 CPU。

NO_HZ_FULL:把非关键定时器迁移到 housekeeping CPU → 隔离 CPU 无 tick 干扰。

八、用户态定时器

API 精度 通知方式
sleep/usleep 阻塞
nanosleep 阻塞
setitimer 信号
timer_create 信号/线程
timerfd_create fd(可 epoll)

推荐 timerfd → 与事件循环组合。

九、观察

cat /proc/timer_list              # 所有定时器(巨大输出)
cat /proc/timer_list | head -50   # 活跃 hrtimer

perf stat -e timer:hrtimer_start -a sleep 1
bpftrace -e 'tracepoint:timer:hrtimer_start { @[kstack(3)] = count(); }'

十、小结


参考文献

工具


上一篇线程化中断 下一篇无滴答内核

同主题继续阅读

把当前热点继续串成多页阅读,而不是停在单篇消费。

2026-06-29 · linux / os

EEVDF 调度器:Linux 6.6 为什么换掉了 CFS

Linux 6.6 用 EEVDF 取代了 CFS 的 SCHED_NORMAL 选取逻辑。从 1995 年原始论文的 lag、eligibility、virtual deadline,到 commit 147f3ef 只重写 placement/pick/preempt,再到本机内核 6.6 上读 sched/debug 把每个任务的 vruntime、eligible 标志、deadline 一一对上 vd=ve+r/w,外加 nice 带宽与 base_slice 抢占两组实测,讲清换的是哪一块、延迟敏感任务凭什么先跑。

2026-07-05 · os

【操作系统百科】实时 OS 巡礼

硬实时与软实时的可调度性边界、VxWorks/QNX/Zephyr 机制对照、Linux PREEMPT_RT 与主线合入、DO-178C/ISO 26262 认证语境,以及选型决策树。

2026-07-06 · os

【操作系统百科】Unikernel

Unikernel 在云上为什么没成主流?MirageOS、IncludeOS、Unikraft、OSv 的设计取舍——库操作系统、启动时间、工具链、调试困难、POSIX 兼容。


By .