把可运行 CPU 集合传递给虚拟机线程
libvirt 将 vCPU 允许使用的宿主 CPU 集合表示为位图,并转换为运行时亲和性配置。
相关概念
工程问题#
一条绑定规则可能包含多个 CPU;接口需要紧凑传输、检查空集,并区分立即生效与保存为持久配置。
实际实现#
qemuDomainPinVcpuFlags 把 cpumap 转为 virBitmap。运行态对在线 vCPU 设置线程亲和性,若存在 cpuset 控制器则先配置 cpuset;持久态保存 vCPU 的 cpumask,两条路径可由 flags 同时请求。
处理流程#
- 把字节数组转换为 CPU 位图
- 校验 vCPU 与非空集合
- 按 flags 更新运行态或持久配置
- 把允许集合传递给对应线程
源码片段#
固定版本 · 原文摘录src/qemu/qemu_driver.cv10.10.0 · L4402–L4421
4402 if (!(pcpumap = virBitmapNewData(cpumap, maplen)))4403 goto endjob;44044405 if (virBitmapIsAllClear(pcpumap)) {4406 virReportError(VIR_ERR_INVALID_ARG, "%s",4407 _("Empty cpu list for pinning"));4408 goto endjob;4409 }44104411 if (def &&4412 qemuDomainPinVcpuLive(vm, def, vcpu, driver, pcpumap) < 0)4413 goto endjob;44144415 if (persistentDef) {4416 virBitmapFree(vcpuinfo->cpumask);4417 vcpuinfo->cpumask = g_steal_pointer(&pcpumap);44184419 ret = virDomainDefSave(persistentDef, driver->xmlopt, cfg->configDir);4420 goto endjob;4421 }qemuDomainPinVcpuFlags
cpumap 从接口字节数组转成 virBitmap,空集合会报错;live 与 persistent 两条路径共用这份集合。运行态交给 qemuDomainPinVcpuLive,持久态接管位图并保存配置,因此该 API 不保证一定立即修改线程亲和性。
收益与取舍#
工程分析带来的收益
- 每个 CPU 仅占一个集合成员位
- 成员判断和集合表达直观
付出的代价
- 工程分析:空间取决于最大 CPU 编号
- 集合只表达允许范围,不表达优先级或权重
可比较的选择
CPU 编号列表极稀疏集合可能更省空间,但成员操作与接口转换需要额外处理。
版本与适用范围#
对应 QEMU 驱动的 vCPU pinning;CPU 亲和性不自动保证独占 CPU,也不能替代 NUMA 内存策略。
参考来源#
源码、官方文档与原始论文01
libvirt · qemuDomainPinVcpuFlags / qemuDomainPinVcpuLive
源码v10.10.0src/qemu/qemu_driver.c · qemuDomainPinVcpuFlags / qemuDomainPinVcpuLive
相关实现与比较#
2 个相关案例QEMU dirty bitmap 为磁盘区间记录是否被写入,使增量备份能够只复制发生变化的范围。
附源码片段 · 存储与数据放置
Linux 普通定时器把较近超时放进细粒度槽,远期超时放进粗粒度槽,使用位图寻找待处理槽。v6.12 的这套时间轮不再逐层级联迁移。
附源码片段 · 调度与资源分配