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

【操作系统百科】定时器

文章导航

分类入口
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-04-27 · os

【操作系统百科】内存回收

Linux 内存回收是 VM 最复杂的子系统之一。本文讲 active/inactive LRU、kswapd 与 direct reclaim、watermark 三线、swappiness 的真实含义、MGLRU 改造、memcg 回收与 PSI。

2026-04-28 · os

【操作系统百科】交换

swap 还值得开吗?本文讲 swap area 基础、swap cache、zram 压缩内存、zswap 前端压缩池、swappiness 的真实含义、容器里的 swap 策略,以及为什么现代 Android 全靠 zram 不靠磁盘。

2026-05-03 · os

【操作系统百科】Slab/SLUB 分配器

buddy 只管页粒度(4K+),内核大多数对象只有几十到几百字节。slab/SLUB 在 buddy 之上做对象级缓存。本文讲 slab 历史、SLUB 接手、SLOB 退场、kmem_cache、per-CPU cache、KASAN 集成。

2026-05-07 · os

【操作系统百科】用户态分配器

glibc malloc、tcmalloc、jemalloc、mimalloc 各有哲学。本文讲 arena、thread cache、size class、madvise 返还策略、碎片与 RSS 膨胀、如何根据负载选分配器。


By .