虚拟机弹性扩缩容 → 运行时添加/移除 vCPU。物理机也有:ACPI CPU 热插拔、维护模式下线核心。
一、先看图
stateDiagram-v2
[*] --> OFFLINE
OFFLINE --> BRINGUP_CPU: cpu_up
BRINGUP_CPU --> AP_ONLINE: 启动 + 初始化
AP_ONLINE --> ONLINE: 注册调度器 + 中断
ONLINE --> TEARDOWN_CPU: cpu_down
TEARDOWN_CPU --> OFFLINE: 迁移任务 + 停止
state BRINGUP_CPU {
[*] --> STARTING
STARTING --> AP_IDLE
}
state TEARDOWN_CPU {
[*] --> AP_DYING
AP_DYING --> [*]
}
二、CPUHP 状态机
// include/linux/cpuhotplug.h
enum cpuhp_state {
CPUHP_OFFLINE,
CPUHP_BRINGUP_CPU,
CPUHP_AP_IDLE_DEAD,
// ... 100+ 个状态
CPUHP_ONLINE,
};每个子系统注册 startup/teardown 回调 → 状态机按序调用。
cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, "mydriver",
my_cpu_online, my_cpu_offline);三、cpu_down 路径
- 停止调度新任务到目标 CPU
- 迁移所有任务到其他 CPU
- 迁移定时器
- 迁移 RCU 回调
- 迁移中断(IRQ affinity)
- 调用所有 teardown 回调
- CPU 进入 OFFLINE 状态
四、迁移的复杂性
4.1 任务迁移
绑定到目标 CPU
的任务(cpuset/taskset)→ 需要放宽
affinity 或失败。
per-CPU 内核线程 → 特殊处理(停止或迁移)。
4.2 定时器迁移
目标 CPU 的所有 timer/hrtimer → 迁移到其他 CPU。
4.3 RCU 迁移
目标 CPU 的 RCU 回调队列 → 迁移到其他 CPU。
nocb CPU 较简单(回调本来就不在该 CPU 处理)。
4.4 中断迁移
目标 CPU 绑定的 IRQ → 重新分配 affinity。
managed IRQ(MSI-X)的处理更复杂。
五、锁竞争
cpu_down 需要获取多个锁:
cpu_hotplug_lock(percpu_rwsem)- 各子系统锁
长时间持锁 → 影响其他 CPU 的操作(如
get_online_cpus() 阻塞)。
六、nohz_full + hotplug
nohz_full CPU 下线 → 需要先恢复 tick → 再走正常下线路径。
陷阱:housekeeping CPU 不能下线(否则无人处理定时器/RCU)。
七、虚拟化场景
7.1 vCPU 热添加
KVM/QEMU 支持运行时添加 vCPU → guest 内核
cpu_up() 新核。
7.2 云弹性
AWS/Azure/GCP 可调整 VM 的 vCPU 数量 → 触发 guest 内 CPU hotplug。
八、回归事故
CPU hotplug 是内核回归重灾区:
- 竞争条件:下线过程中有请求到达
- 遗忘回调:子系统未注册 teardown → 资源泄漏
- 死锁:锁顺序问题
内核 CI 必须测试 CPU hotplug 路径。
九、观察
# 查看在线 CPU
cat /sys/devices/system/cpu/online
# 0-7
# 下线 CPU 3
echo 0 > /sys/devices/system/cpu/cpu3/online
# 上线
echo 1 > /sys/devices/system/cpu/cpu3/online
# 查看 hotplug 状态
cat /sys/devices/system/cpu/cpu3/hotplug/state
dmesg | grep -i "cpu.*offline\|cpu.*online"十、小结
- CPUHP 状态机管理 100+ 个子系统的 startup/teardown
- cpu_down 需要迁移任务、定时器、RCU、中断
- 锁竞争和回归事故是主要风险
- 虚拟化和云弹性是主要使用场景
- housekeeping CPU 不能下线
参考文献
kernel/cpu.cDocumentation/core-api/cpu_hotplug.rst- Thomas Gleixner, “CPU hotplug rework.” 2016
include/linux/cpuhotplug.h
工具
/sys/devices/system/cpu/cpuN/online/sys/devices/system/cpu/cpuN/hotplug/statedmesg- stress-ng –cpu-hotplug
文章导航
读完这篇,下一步读什么
优先读同系列或同问题的下一篇,把单篇消费变成主题集群。
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 与安全加固。