virsh本身不支持在线动态热插拔物理内存,仅能触发操作;真正生效需满足xml预配slots、guest numa启用、内核支持热插等前提,且热插后须在guest内手动上线内存块。

virsh 本身不支持「在线动态热插拔」物理内存——它只能触发热插操作,但能否成功、是否上线、是否可用,完全取决于虚拟机配置、Guest 内核能力、NUMA 设置和底层硬件约束。强行调用 virsh setmem 或改 XML 后不重启,99% 的情况不会生效,甚至可能卡死。
virsh setmem 和 virsh setmaxmem 的实际作用
这两个命令只修改 libvirt 管理层的内存“软限制”或“硬上限”,不是真正向 Guest 插入新内存条:
-
virsh setmem vm-name 4194304(单位 KiB):仅尝试调整当前分配内存,若 Guest 不支持热插或未上线 slot,会静默失败或报错operation failed: cannot set memory -
virsh setmaxmem vm-name 8388608 --config:只改 XML 中的<memory></memory>和<maxmemory></maxmemory>,重启后才生效,不是热操作 - 二者都不触碰 QEMU 的 memory hotplug 接口,也不触发 Guest 内核的 memory probe 流程
真正能热插内存的前提条件
缺一不可,否则 virsh 命令哪怕执行成功,Guest 里也看不到新内存:
- 虚拟机 XML 必须提前配置
<maxmemory></maxmemory>(含slots属性),例如:<maxmemory unit="KiB" slots="4">16777216</maxmemory>—— 没配slots,QEMU 根本不预留热插接口 - 必须启用 Guest NUMA:
<cpu>...<numa><cell id="0" cpus="0-3" memory="4194304"></cell></numa></cpu>,否则内核拒绝上线新内存 - Guest 内核需开启
CONFIG_MEMORY_HOTPLUG(Linux)或 Windows Server 2012+(且为 Standard/Datacenter 版) - 热插大小必须是
block_size_bytes的整数倍(lsmem | grep "Memory block size"查,常见为 128MiB) - x86 平台 machine type 至少为
pc-i440fx-1.5,AArch64 至少为virt-4.1
热插内存的完整操作链
不能跳步,顺序错一步就卡在“已插入但未上线”状态:
- 先确认 Guest NUMA node:运行
virsh dumpxml vm-name | grep -A5 numa,记下 node id(如id='0') - 执行热插(指定 node):
virsh memtune vm-name --hard-limit 8388608 --config不行,要用:virsh attach-device vm-name /tmp/mem.xml --live --config,其中/tmp/mem.xml内容为:<memory model="dimm"><target><size unit="KiB">2097152</size><node>0</node></target></memory>
- 登录 Guest,检查是否识别:
lsmem看是否有 offline block;若有,手动上线:echo online > /sys/devices/system/memory/memoryX/state(X 为 block 编号) - 验证:
free -h或cat /proc/meminfo | grep MemTotal
为什么你执行 virsh attach-device 后 df -h 或 free -h 没变化
这是最常被忽略的环节:热插只是把内存设备加进 Guest 的 sysfs,但默认处于 offline 状态。Linux 不自动上线,Windows 需进“服务器管理器→内存”手动刷新。如果你没做 echo online > /sys/.../state 或没配 udev 规则,free 就永远看不到新增容量——这不是 virsh 的问题,是 Guest 自身行为。











