默认 Linux 每秒产生 250-1000 次 tick 中断——更新时间、检查调度。但在低延迟场景(DPDK、交易系统),每次 tick 都是几微秒的噪声。
一、先看图
flowchart LR
subgraph 传统 tick
TICK[周期 tick<br/>250-1000 Hz] --> OVERHEAD[每 tick 中断<br/>~2-5μs]
end
subgraph NO_HZ_IDLE
IDLE[空闲时] --> SKIP1[跳过 tick<br/>省电]
end
subgraph NO_HZ_FULL
RUN[运行用户态] --> SKIP2[跳过 tick<br/>零干扰]
SKIP2 --> HK[housekeeping CPU<br/>处理杂务]
end
classDef old fill:#f0883e22,stroke:#f0883e,color:#adbac7;
classDef new fill:#3fb95022,stroke:#3fb950,color:#adbac7;
class TICK,OVERHEAD old
class IDLE,SKIP1,RUN,SKIP2,HK new
二、三种模式
2.1 CONFIG_HZ_PERIODIC
传统周期 tick。每 CPU 每秒 HZ 次中断。
2.2 NO_HZ_IDLE(默认)
CPU 空闲时停止 tick → 省电(C-state 进入更深层)。
有任务运行 → 恢复 tick。
2.3 NO_HZ_FULL
CPU 上只有一个可运行任务 → 停止 tick → 用户态不受 tick 干扰。
nohz_full=2-7
三、housekeeping CPU
NO_HZ_FULL CPU 不处理:
- tick(定时器中断)
- RCU 回调
- 非绑定 workqueue
- 某些内核线程
这些工作由 housekeeping CPU 承担(通常 CPU 0-1)。
四、isolcpus 与 nohz_full
isolcpus=nohz,domain,managed_irq,2-7
nohz_full=2-7
rcu_nocbs=2-7
三者配合:
isolcpus:从调度域移除 → 不自动分配任务nohz_full:停止 tickrcu_nocbs:RCU 回调在 housekeeping CPU 处理
五、RCU nocb
rcu_nocbs=2-7
隔离 CPU 不运行 RCU 回调 → 由 rcuog/rcuop
线程在 housekeeping CPU 运行。
避免 RCU grace period 处理干扰隔离 CPU。
六、副作用
| 副作用 | 原因 |
|---|---|
| /proc/stat CPU 时间不准 | 无 tick 不更新统计 |
| perf 采样不准 | 无 tick 触发采样 |
| 负载均衡不触发 | 隔离 CPU 不在调度域 |
| IPI 仍存在 | TLB shootdown、RCU 等 |
七、实际配置示例
# 内核启动参数
GRUB_CMDLINE_LINUX="isolcpus=nohz,domain,managed_irq,2-7 \
nohz_full=2-7 rcu_nocbs=2-7 \
irqaffinity=0-1 \
nosoftlockup"# 将应用绑定到隔离 CPU
taskset -c 2-7 ./my_app
# 或 cgroup
echo 2-7 > /sys/fs/cgroup/cpuset/isolated/cpuset.cpus八、DPDK/SPDK 场景
DPDK 用户态网络:polling 模式 → 一个核 100% 运行 PMD 线程 → tick 是噪声。
NO_HZ_FULL → PMD 线程零内核干扰 → 稳定低延迟。
九、观察
# 检查 nohz_full 生效
cat /sys/devices/system/cpu/nohz_full
# 2-7
# tick 统计
cat /proc/interrupts | grep LOC # Local timer
# 隔离 CPU 的 LOC 应该很低
# 残余中断
perf stat -C 2 -e irq:* sleep 10十、小结
- NO_HZ_IDLE:空闲时跳 tick → 省电
- NO_HZ_FULL:运行时也跳 tick → 零干扰
- isolcpus + nohz_full + rcu_nocbs 三件套
- housekeeping CPU 承担所有杂务
- 副作用:统计不准、perf 采样缺失
参考文献
Documentation/timers/NO_HZ.rstkernel/time/tick-sched.c- Frederic Weisbecker, “Full dynticks.” 2013
- DPDK documentation, “CPU Isolation.”
工具
/sys/devices/system/cpu/nohz_fulltaskset/cset- cyclictest
- perf
文章导航
读完这篇,下一步读什么
优先读同系列或同问题的下一篇,把单篇消费变成主题集群。
CPU 调度:CFS 的虚拟运行时间与 EEVDF 的虚拟截止期
从比例份额调度的论文谱系出发,对照 Linux v6.6 与 v6.12 fair.c 源码,解释 CFS 的 vruntime、EEVDF 的 lag/eligible/deadline,并用确定性模拟复现延迟与 lag 的差异。
I/O 调度:在寻道、队列深度与公平性之间取舍
从电梯算法到 blk-mq,解释 Linux I/O 调度器为何在 HDD 上排序、在共享设备上保公平、在 NVMe 上常选择 none,并用确定性模拟展示寻道距离与队列尾延迟的取舍。
用户态内存分配器:size class、线程缓存与碎片边界
从 Wilson 分配器综述到 jemalloc、gperftools tcmalloc 与 mimalloc 的源码路径,解释 size class、线程缓存、跨线程释放和 RSS 碎片;用可复现实验说明不能只凭 allocator 名字下结论。
伙伴系统与 SLUB:Linux 物理页和小对象分配的边界
以 Linux v6.6 源码和确定性模拟为准,解释伙伴系统的 split/coalesce、migratetype 反碎片策略,以及 SLUB 的 per-CPU freelist、partial list 与安全加固。