前阵子有朋友问我,能不能在办公用的x86服务器上搞一个ARM64的虚拟机。他手头有个项目必须用ARM64版的应用做验证,但又不想立刻去租云上的ARM实例。这个需求我太熟了,去年我在CentOS 8上把这套流程完整走了一遍,中间踩的坑比想象中多:UEFI固件找不到、VNC黑屏半小时、Kernel panic、网络不通、纯软件模拟慢到让人怀疑人生……标题里那几个热搜词,什么“qemu模拟arm64”“arm64和amd64有何不同”“uefi引导修复”,正好把大家最关心的点全点出来了。
这篇文章我就把这套流程完整拆开,从基础概念讲到装包、建机、UEFI配置,再到排错思路和日常管理。目标是让一个没碰过ARM虚拟化的人,照着文章也能在CentOS 8上把ARM64虚拟机跑起来,并且知道出问题时该从哪里下手查。
1. 先分清“模拟”与“虚拟化”:这决定了你的宿主机该怎么选
1.1 arm64和amd64的差异为什么会让KVM失效
很多人第一次接触这事,都会困惑:都是64位,怎么就不能用KVM了?ARM64(官方叫法AArch64)和amd64(大家常说的x86_64)是两套完全不同的指令集,底层的寄存器数量、指令编码、访存模型全都不一样。KVM的工作方式是把CPU的硬件虚拟化扩展直接暴露给虚拟机,让guest的指令在物理CPU上原样执行。这个前提是guest架构和宿主架构一致:x86的KVM只能跑x86 guest,ARM的KVM只能跑ARM guest。所以在x86宿主机上想跑ARM64 guest,KVM这条路天然是不通的。
那x86上怎么跑ARM64?靠的是QEMU的TCG模式(Tiny Code Generator),纯软件做二进制翻译,把ARM64指令逐条翻译成x86指令再执行。代价就是性能差距非常明显:CPU密集任务通常只有原生性能的10%到20%,有些场景连5%都不到。反过来,如果你的宿主机本身就是ARM64服务器,那就可以用KVM硬件加速,性能和裸机几乎没区别,整个流程也会顺很多。
所以动手之前,先问自己一句:我的宿主是x86还是ARM?这直接决定了后面所有参数,尤其是--virt-type怎么填。
1.2 一条命令确认当前宿主能走哪条路
别猜,直接查。先看KVM设备节点:
ls -l /dev/kvm有这个文件说明宿主CPU支持虚拟化且KVM模块已加载。再看libvirt对aarch64架构的能力上报:
virsh domcapabilities --machine virt --arch aarch64 | head -40这条命令比较关键。在ARM64宿主机上,返回结果里会有<domain type='kvm'>这样的列表;在x86宿主机上,通常只有<domain type='qemu'>,意思是只能用TCG模拟。如果你装了QEMU,还可以直接看加速器列表:
qemu-system-aarch64 -accel help会列出tcg、kvm等可用的加速后端。x86宿主上硬选kvm跑aarch64 guest,启动时会报类似kvm_init_vcpu failed的错误,原因就是前面说的架构不匹配。
判断好之后,在virt-install里对应填:
- ARM64宿主:
--virt-type kvm - x86宿主:
--virt-type qemu(强制走TCG)
1.3 两种方案的性能预期与适用场景
| 宿主架构 | 加速方式 | 性能表现 | 适合干什么 |
|---|---|---|---|
| ARM64 | KVM | 接近原生 | CI构建、服务部署测试、交叉编译验证、跑容器 |
| x86_64 | TCG | CPU密集任务下降明显 | 临时验证、跑通流程、环境测试、学ARM64 Linux |
TCG模式下我建议guest的vCPU控制在2到4个,别再多了。QEMU的TCG在旧版本里是单线程翻译,vCPU越多锁竞争越明显,4核可能比2核还要慢。内存4G起步,8G比较舒服。如果你要跑的是编译任务或者高并发服务,趁早别指望TCG能扛生产负载,老老实实上ARM真机或云实例。
2. CentOS 8宿主环境准备:源失效处理、依赖安装与设备验证
2.1 处理CentOS 8源失效的坑
这是CentOS 8用户绕不开的第一个坑:CentOS 8在2021年底已经EOL,默认的mirrorlist早就失效了,直接跑dnf install几乎必然报错。官方把历史仓库挪到了vault.centos.org,手动切过去就行:
cd /etc/yum.repos.d/ sed -i 's/mirrorlist=/#mirrorlist=/g' CentOS-* sed -i 's|#baseurl=http://mirror.centos.org|baseurl=http://vault.centos.org|g' CentOS-* dnf clean all && dnf makecache如果你不想在这上面花时间,也可以直接装Rocky Linux 8或AlmaLinux 8,它们是CentOS 8的完全兼容替代,下面所有命令在Rocky/Alma上一样跑得通。我个人现在做实验都直接用Rocky,少踩很多源的问题。
2.2 安装libvirt、QEMU与AAVMF固件
需要装的包有四个部分:QEMU模拟器、UEFI固件、libvirt管理栈、镜像辅助工具。
dnf install -y qemu-system-arm edk2-aarch64 libvirt virt-install cloud-utils逐个说明一下:
qemu-system-arm提供qemu-system-aarch64这个模拟器二进制。如果提示找不到包,先跑dnf provides '*/qemu-system-aarch64'搜一下,再不行就启用EPEL兜底。edk2-aarch64提供AAVMF固件,也就是ARM64虚拟机用的UEFI固件。装完后检查/usr/share/AAVMF/目录,里面会有AAVMF_CODE.fd和AAVMF_VARS.fd两个文件,后面会细讲。libvirt和virt-install是管理栈,virt-install是咱们建机的主力工具。cloud-utils提供cloud-localds命令,用来生成cloud-init的seed镜像。
如果你在x86宿主上,还需要确认系统里有没有qemu-kvm这个基础包。CentOS 8的qemu-kvm虽然默认是给x86 KVM用的,但有些版本会带上多架构模拟支持,装了没坏处:
dnf install -y qemu-kvm2.3 启动服务并验证aarch64能力
装完先启动libvirtd:
systemctl enable --now libvirtd systemctl status libvirtd --no-pager然后做一组快速验证,确保后面建机时不会因为环境问题卡住:
virsh version qemu-system-aarch64 --version ls -l /usr/share/AAVMF/ virsh domcapabilities --machine virt --arch aarch64 | grep -i firmware -A5最后一条很关键。如果AAVMF固件装好了,这里会列出firmware相关的信息,包括loader路径。如果这一行是空的,说明libvirt没找到ARM64的UEFI固件,后面virt-install时--boot uefi一定会报错。这时候回头检查edk2-aarch64是否真的装上了。
3. 镜像准备:为什么我推荐云镜像而不是ISO
3.1 Ubuntu ARM64云镜像的下载与磁盘处理
第一次搭ARM64虚拟机的人,最容易犯的错是直接下个ISO去装。在TCG模拟下,Ubuntu Server ARM64的安装器跑起来那个慢啊,一个基础系统装两小时都算快的。所以我强烈建议用云镜像(cloud image)方案,它是厂商预先做好的最小系统,配合cloud-init在首次启动时完成配置,几分钟就能进系统。
以Ubuntu 22.04为例:
cd /var/lib/libvirt/images wget https://cloud-images.ubuntu.com/releases/22.04/release/ubuntu-22.04-server-cloudimg-arm64.img下载下来的是个大约600MB的qcow2镜像,自带GPT分区表。你可以用fdisk -l看一下,通常是两个分区:第一个是EFI System Partition,vfat格式,里面放着grubaa64.efi和BOOTAA64.EFI;第二个是ext4根分区。这正是它能直接UEFI启动的原因,也是咱们后面验证固件有没有配对的依据。
接下来把镜像拷一份作为虚拟机磁盘,千万不要直接动原始文件:
cp ubuntu-22.04-server-cloudimg-arm64.img arm64-vm.qcow2 qemu-img resize arm64-vm.qcow2 20G原始云镜像根分区只有2G,扩容之后cloud-init里的growpart会在首次启动时自动把根分区扩展到整个磁盘,你不需要手工处理分区表。
3.2 用cloud-init生成带密码和SSH的seed镜像
云镜像是没有默认密码的,第一次启动必须通过cloud-init注入配置。咱们用一个单独的seed镜像来传递这些信息:
cat > user-data <<EOF #cloud-config password: YourPassword123 chpasswd: expire: False ssh_pwauth: True ssh_authorized_keys: - ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAA... yourkey EOF cat > meta-data <<EOF instance-id: arm64-vm-001 local-hostname: arm64-vm EOF cloud-localds seed.img user-data meta-datacloud-localds会生成一个带cidata卷标的ISO镜像。如果没有cloud-utils,也可以用mkisofs手动做:
mkisofs -output seed.img -volid cidata -joliet -rock user-data meta-data这个seed.img在virt-install里作为第二块磁盘挂给虚拟机,cloud-init在首次启动时会自动识别并应用里面的配置。root密码、SSH公钥、主机名全都由它搞定。
3.3 什么场景才需要走ISO安装
现在讲讲ISO方案的适用边界。在ARM64宿主上用KVM跑,ISO安装完全没问题,速度跟装真机一样。但在x86宿主上用TCG模拟,ISO安装就是噩梦,Live installer的每个界面切换都要等几十秒。
除非你需要的发行版没有官方云镜像,否则不要受这个罪。非要ISO的话,可选的有Debian ARM64 netinst、Fedora ARM64 Everything、CentOS Stream 9 ARM64这些。国内常用的openEuler、麒麟也有ARM64版本,流程和Ubuntu完全一致,只是云镜像的cloud-init配置细节略有差异。
4. virt-install建机实战:一条命令拆开讲透
4.1 完整命令与参数含义
下面这条命令是x86宿主机的版本,ARM64宿主只需要改两处,我后面会说。先看完整命令:
virt-install \ --name arm64-vm \ --memory 4096 \ --vcpus 4 \ --arch aarch64 \ --machine virt \ --cpu cortex-a72 \ --os-variant ubuntu22.04 \ --disk path=/var/lib/libvirt/images/arm64-vm.qcow2,device=disk,bus=virtio,format=qcow2 \ --disk path=/var/lib/libvirt/images/seed.img,device=disk,bus=virtio,format=raw \ --network network=default,model=virtio \ --graphics vnc,listen=127.0.0.1 \ --boot uefi \ --virt-type qemu \ --noautoconsole逐个参数解释:
--arch aarch64:告诉virt-install要建ARM64虚拟机,它会自动选择qemu-system-aarch64。--machine virt:ARM64虚拟机在QEMU里有好几种机型,virt是官方推荐的通用机型,支持UEFI和virtio设备。不要用老旧的integratorcp、versatilepb这些。--cpu cortex-a72:TCG模式下指定一个具体的ARM CPU型号。这里千万不能用host,因为宿主是x86,libvirt没法把x86的CPU特性映射给ARM64 guest。--os-variant ubuntu22.04:让virt-install按照Ubuntu 22.04的默认特性做优化。如果提示找不到这个系统,用osinfo-query os | grep -i ubuntu查一下可用的variant名字,实在不行就填generic。--disk:第一块是系统盘,第二块是cloud-init的seed盘。bus=virtio是性能最好的选择,后面会细说。--network network=default,model=virtio:使用libvirt默认的NAT网络,网卡模型用virtio。--graphics vnc,listen=127.0.0.1:只监听本机VNC,避免暴露到公网。需要远程访问时用SSH隧道。--boot uefi:让libvirt自动为ARM64虚拟机寻找AAVMF固件。--virt-type qemu:强制使用TCG模拟。这是x86宿主机上最关键的一个参数,不填的话virt-install可能报“找不到适合aarch64的hypervisor”。--noautoconsole:不自动附加控制台,防止命令卡在console界面。
ARM64宿主上只需要改两处:
--cpu host-passthrough \ --virt-type kvm \--cpu host-passthrough直接把物理CPU特性透传给guest,性能最好。如果不想指定CPU,让libvirt用默认值也行。
4.2 UEFI固件的两种指定方式与NVRAM机制
--boot uefi是懒人写法,virt-install会调用libvirt的能力查询,自动找到/usr/share/AAVMF/AAVMF_CODE.fd,并为这台虚拟机复制一份独立的AAVMF_VARS.fd到/var/lib/libvirt/qemu/nvram/arm64-vm_VARS.fd。
如果不放心自动查找的结果,或者你的AAVMF路径比较特殊,可以手动指定:
--boot loader=/usr/share/AAVMF/AAVMF_CODE.fd,loader_ro=yes,nvram_template=/usr/share/AAVMF/AAVMF_VARS.fd这里有两个细节建议理解一下,因为后面排错经常用到:
第一个是loader_ro=yes。QEMU把固件当pflash设备映射给虚拟机,固件代码区必须只读,防止虚拟机运行时把固件本体写坏。可写的NVRAM里只放UEFI变量,比如BootOrder、Boot####这些启动项记录。
第二个是NVRAM为什么要为每台虚拟机单独复制。如果所有虚拟机共用一份VARS,A虚拟机写的启动项会被B虚拟机读到,两台机器的BootOrder互相干扰,轻则启动变慢,重则直接找不到系统。libvirt在创建虚拟机时自动从模板复制一份独立VARS文件,就是为了隔离这种状态。
4.3 创建后的验证与首次登录
命令执行完没有报错,先确认虚拟机状态:
virsh list --all virsh start arm64-vm virsh domifaddr arm64-vm --source leasedomifaddr会从libvirt默认网络的DHCP租约里读出guest的IP地址。拿到IP之后SSH登录:
ssh ubuntu@<IP>Ubuntu云镜像默认用户是ubuntu,密码就是你在user-data里设置的那个,或者用你注入的SSH密钥直接登录。登录进去第一件事:
df -h uname -muname -m输出aarch64就说明你已经成功进了一个真正的ARM64系统。df -h看看根分区是否已经自动扩容到20G。
5. AAVMF固件工作机理:从pflash到grubaa64.efi
5.1 AAVMF_CODE.fd与AAVMF_VARS.fd的分工
做过x86平台的同学应该对OVMF不陌生,AAVMF和OVMF同源,都是EDK2工程编出来的UEFI实现,区别只在于目标架构。OVMF对应x86_64,AAVMF对应aarch64。
AAVMF包含两个文件:
AAVMF_CODE.fd:固件本体,只读。里面是完整的UEFI实现,包括CPU初始化、串口和显卡驱动、设备枚举逻辑、Boot Manager。AAVMF_VARS.fd:NVRAM变量存储,可写。保存了BootOrder、Boot####启动项条目,以及Secure Boot的密钥库。
打一个不太严谨但很好记的比方:CODE像主板的BIOS芯片,VARS像主板上的CMOS加电池。BIOS芯片里的程序不能被普通指令改写,但CMOS里的配置会被每次开机时的设置项改写。
这两个文件在virt-install里的协作方式前面已经说过了,libvirt把CODE映射为只读pflash,把VARS的副本映射为可写pflash。如果你手动改过domain XML,会看到类似这样的结构:
<os> <type arch='aarch64' machine='virt'>hvm</type> <loader readonly='yes' type='pflash'>/usr/share/AAVMF/AAVMF_CODE.fd</loader> <nvram>/var/lib/libvirt/qemu/nvram/arm64-vm_VARS.fd</nvram> </os>5.2 ARM64虚拟机完整的UEFI启动链路
理解启动链路对排查问题非常重要。一台ARM64虚拟机从按下启动到进入系统,大致经过这几步:
- QEMU启动,CPU从复位向量开始执行,AAVMF_CODE被映射到virt机型的pflash地址。
- AAVMF初始化CPU、内存、中断控制器(GIC)、串口、显示设备。
- UEFI驱动枚举virtio总线上的设备,识别出磁盘和网卡。
- Boot Manager读取NVRAM里的BootOrder启动顺序。
- 对每个启动项,UEFI去对应磁盘上扫描EFI System Partition,尝试加载
\EFI\BOOT\BOOTAA64.EFI(可移动介质路径)或具体的grub路径。 - grub加载
grub.cfg,读取内核vmlinuz和initrd.img,跳转到内核入口。 - Linux内核启动,挂载根分区,进入系统。
Ubuntu ARM64云镜像的ESP分区里同时有EFI/BOOT/BOOTAA64.EFI和EFI/ubuntu/grubaa64.efi,所以UEFI固件怎么找都能引导成功。这也是为什么我用Ubuntu云镜像作为教程示例——它是检验UEFI配置是否正确的最好载体。
5.3 进了UEFI Shell怎么排查启动项
当NVRAM里的BootOrder被搞乱,或者ESP分区里的引导文件缺失时,AAVMF会掉进UEFI Shell。不要慌,这在某种程度上是好事——说明固件、内存、磁盘控制器都是好的,问题出在启动项配置上。
在Shell里可以手工加载引导器:
Shell> fs0: FS0:\> ls FS0:\> cd \EFI\BOOT FS0:\EFI\BOOT> BOOTAA64.EFI如果能进展到grub菜单,说明引导文件本身没问题,纯粹是BootOrder丢了。用bcfg命令修复启动项:
FS0:\> bcfg boot add 0 FS0:\EFI\BOOT\BOOTAA64.EFI "Ubuntu" FS0:\> bcfg boot dump如果折腾了一圈还是起不来,还有一个更粗暴但有效的办法:重置NVRAM。把虚拟机关机后,用virsh undefine --nvram arm64-vm把domain定义连同NVRAM一起删掉,再用原来的virt-install命令重新建一次。磁盘镜像还在,数据不丢,只是把UEFI变量库恢复到出厂状态。
6. 常见坑点实录:黑屏、panic、慢到怀疑人生的完整排查
6.1 坑:启动黑屏无任何输出
这是问得最多的一个问题。virt-install命令执行成功,virsh list也能看到虚拟机在跑,但VNC窗口一片黑。
我的排查链路是这样的:
第一步,先确认系统是不是真的没启动。执行virsh console arm64-vm,如果能看到grub菜单或者内核日志,说明系统在正常跑,问题出在显卡输出链路上。Ubuntu的ARM64云镜像默认配置了console=ttyAMA0,115200的内核参数,所以串口控制台是能用的。
第二步,看domain XML里的video设备配置:
virsh edit arm64-vm如果libvirt默认生成了virtio-gpu,在TCG模式下渲染会比较慢,容易出现长时间黑屏。可以改成bochs或cirrus这种简单的显卡模型:
<video> <model type='bochs'/> </video>第三步,如果串口也没输出,那就是固件阶段就出问题了,大概率是loader路径不对或者固件根本没加载。检查virsh edit里的loader配置是否指向真实存在的AAVMF文件。
6.2 坑:Kernel panic / VFS Unable to mount root
能进grub,但内核启动时报VFS: Unable to mount root fs on unknown-block(254,0),这个错误几乎都是root设备名对不上导致的。
ARM64云镜像的grub配置里写死了root设备是virtio-blk盘的第二个分区,也就是/dev/vda2。如果你把磁盘bus换成了sata或ide,设备名会变成/dev/sda2,内核按root=/dev/vda2去找就必然扑空。
解决办法很简单:磁盘统一用bus=virtio,不要手工覆盖内核的root参数。如果你用的是自己裁剪的内核,确认编译时打开了CONFIG_VIRTIO_BLK=y和CONFIG_VIRTIO_PCI=y,否则内核根本没有virtio磁盘驱动,连vda设备都枚举不出来。
6.3 坑:网络不通
虚拟机起来了,IP就是拿不到。排查链路如下:
先看宿主侧的libvirt网络:
virsh net-list --all virsh net-dumpxml defaultdefault网络应该存在且是active状态。再看domain XML里的interface配置:
<interface type='network'> <source network='default'/> <model type='virtio'/> </interface>确认网卡模型是virtio。进guest看内核有没有识别到网卡:
dmesg | grep virtio-net如果没有输出,要么是内核缺virtio_net模块,要么是网卡模型和驱动不匹配。可以试试把网卡模型改成e1000,ARM64 virt机型支持这个模拟设备,驱动基本都编译在内核里,兼容性比virtio更稳(虽然性能差一些)。
还有一种常见情况是防火墙干扰。CentOS 8的firewalld在某些版本和libvirt配合不好,会挡住vnet和virbr0桥之间的流量。排查时可以临时停掉防火墙看是否恢复:
systemctl stop firewalld能恢复的话,就把libvirt相关接口和网段加入到firewalld的信任区,或者干脆配置成开机不启动防火墙(内网测试环境这么做问题不大)。
6.4 坑:TCG模拟慢到无法安装系统
如果你是倔强地选择ISO安装,又是在x86宿主上,那这个坑基本躲不掉。TCG模拟本身就慢,Ubuntu的Live Server安装器又是个重量级应用,每个安装步骤的界面渲染都是几何级的时间消耗。
我的建议很直接:
- 换云镜像。这是最彻底的解法,从下载到进系统只要几分钟。
- vCPU控制在2到4个,别贪多。
- CPU模型用
cortex-a72,别用max。max会开启更多指令集特性,某些特性在TCG下会走慢路径。 - 磁盘加
cache=writeback参数,减少模拟层的同步开销。 - 宿主机上执行
dnf module list virt看看有没有更新版本的QEMU模块流可以启用,新版本QEMU的多线程TCG改进明显。
如果你正在跑的是apt update这类的网络操作,TCG下慢是正常的,毕竟翻译层在CPU密集和IO路径上都有开销。忍着点,多等一会儿就好。
6.5 坑:CPU模型、磁盘总线与串口参数
最后集中列几个容易忽略的细节:
- CPU模型:TCG下不要用
--cpu host,libvirt会尝试把x86宿主CPU特性映射给ARM64 guest,这在架构层面就是无效的。用cortex-a72或cortex-a76。 - 固件别混用:AAVMF和OVMF是两套不同架构的固件,ARM64 guest里指定OVMF路径会直接启动失败,反之亦然。别图省事从一个虚拟机复制XML到另一个。
- osinfo版本过旧:CentOS 8自带的libosinfo数据库比较老,可能不认识
ubuntu22.04这个variant。用osinfo-query os | grep -i ubuntu查一下,大不了用generic,功能上没损失。 - 串口控制台:需要靠串口登录的时候,guest内核cmdline必须带
console=ttyAMA0,115200。Ubuntu云镜像默认配好了,但你自己折腾其他系统镜像时要留意。TCG下用virsh console连串口比等VNC出来要可靠得多。 - 时间漂移:TCG模拟下guest时钟容易漂移,装上NTP服务让它自动同步,比手动date强一万倍。
7. 日常管理:快照、克隆、调优与文件交换
7.1 virsh常用命令速查
虚拟机建好之后,日常维护基本都靠virsh:
virsh list --all # 查看所有虚拟机 virsh start arm64-vm # 启动 virsh shutdown arm64-vm # 优雅关机 virsh reboot arm64-vm # 重启 virsh domifaddr arm64-vm --source lease # 查IP virsh console arm64-vm # 连串口控制台 virsh dominfo arm64-vm # 查看配置摘要 virsh edit arm64-vm # 编辑XML配置 virsh vcpuinfo arm64-vm # 查看vCPU状态7.2 快照与克隆的注意事项(含NVRAM与machine-id)
快照是测试场景的好帮手:
virsh snapshot-create-as arm64-vm clean_base "刚装好的干净系统" virsh snapshot-list arm64-vm virsh snapshot-revert arm64-vm clean_base这里有个容易忽略的细节:libvirt的虚拟机快照默认不包含NVRAM文件。也就是说,你回滚到某个快照时,磁盘回到了过去,但UEFI变量库还是当前状态。大多数情况下这没什么影响,但如果回滚前后系统的引导方式变了,可能出现启动顺序错乱。保险起见,重要节点手动备份一下VARS文件:
cp /var/lib/libvirt/qemu/nvram/arm64-vm_VARS.fd ~/arm64-vm_VARS.fd.bak克隆也经常用:
virt-clone --original arm64-vm --name arm64-vm-2 --file /var/lib/libvirt/images/arm64-vm-2.qcow2virt-clone会生成新的MAC地址,但不会改guest内部的machine-id。两台克隆出来虚拟机如果machine-id一样,DHCP、systemd日志、某些集群软件都会出诡异问题。启动克隆机后进guest执行:
sudo rm -f /etc/machine-id /var/lib/dbus/machine-id sudo systemd-machine-id-setup sudo cloud-init clean --machine-id然后再重启一次,让cloud-init重新生成实例身份。
7.3 性能调优方向与宿主机文件传输
TCG模式下能做的调优有限,核心就几点:vCPU别多、CPU模型别选max、磁盘加writeback、guest里跑NTP。ARM64宿主的KVM模式下空间就大了,比如给virtio-blk配置iothread:
<iothreads>1</iothreads> ... <disk type='file' device='disk'> <driver name='qemu' type='qcow2' cache='writeback' iothread='1'/> ... </disk>这种配置会让磁盘IO有独立的处理线程,多队列场景下吞吐提升明显,适合跑数据库之类IO密集的应用。文件传输方面,最省事的就是SSH。先从virsh domifaddr --source lease拿到IP,然后scp、rsync随便用。如果想要更顺滑的共享目录体验,也可以guest里搭NFS或SMB服务,但这属于额外的运维工量了,平时传个包用scp完全够。
最后说点题外话。折腾ARM64虚拟机这件事,第一次走通确实有点门槛,但抓住两条主线就全通了:宿主架构决定加速方式,UEFI固件决定引导链路。我现在的习惯是把这套流程固化成脚本,镜像路径、seed内容、virt-install参数全部参数化,换台机器直接跑几行命令就能开出一台ARM64环境。如果你也经常需要ARM64的测试机器,强烈建议做同样的沉淀,省下来的时间够多喝好几杯咖啡了。