news 2026/9/16 9:54:01

CentOS 8上用QEMU搭建ARM64虚拟机完整指南

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
CentOS 8上用QEMU搭建ARM64虚拟机完整指南

前阵子有朋友问我,能不能在办公用的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 两种方案的性能预期与适用场景

宿主架构加速方式性能表现适合干什么
ARM64KVM接近原生CI构建、服务部署测试、交叉编译验证、跑容器
x86_64TCGCPU密集任务下降明显临时验证、跑通流程、环境测试、学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.fdAAVMF_VARS.fd两个文件,后面会细讲。
  • libvirtvirt-install是管理栈,virt-install是咱们建机的主力工具。
  • cloud-utils提供cloud-localds命令,用来生成cloud-init的seed镜像。

如果你在x86宿主上,还需要确认系统里有没有qemu-kvm这个基础包。CentOS 8的qemu-kvm虽然默认是给x86 KVM用的,但有些版本会带上多架构模拟支持,装了没坏处:

dnf install -y qemu-kvm

2.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-data

cloud-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 lease

domifaddr会从libvirt默认网络的DHCP租约里读出guest的IP地址。拿到IP之后SSH登录:

ssh ubuntu@<IP>

Ubuntu云镜像默认用户是ubuntu,密码就是你在user-data里设置的那个,或者用你注入的SSH密钥直接登录。登录进去第一件事:

df -h uname -m

uname -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虚拟机从按下启动到进入系统,大致经过这几步:

  1. QEMU启动,CPU从复位向量开始执行,AAVMF_CODE被映射到virt机型的pflash地址。
  2. AAVMF初始化CPU、内存、中断控制器(GIC)、串口、显示设备。
  3. UEFI驱动枚举virtio总线上的设备,识别出磁盘和网卡。
  4. Boot Manager读取NVRAM里的BootOrder启动顺序。
  5. 对每个启动项,UEFI去对应磁盘上扫描EFI System Partition,尝试加载\EFI\BOOT\BOOTAA64.EFI(可移动介质路径)或具体的grub路径。
  6. grub加载grub.cfg,读取内核vmlinuz和initrd.img,跳转到内核入口。
  7. Linux内核启动,挂载根分区,进入系统。

Ubuntu ARM64云镜像的ESP分区里同时有EFI/BOOT/BOOTAA64.EFIEFI/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=yCONFIG_VIRTIO_PCI=y,否则内核根本没有virtio磁盘驱动,连vda设备都枚举不出来。

6.3 坑:网络不通

虚拟机起来了,IP就是拿不到。排查链路如下:

先看宿主侧的libvirt网络:

virsh net-list --all virsh net-dumpxml default

default网络应该存在且是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安装器又是个重量级应用,每个安装步骤的界面渲染都是几何级的时间消耗。

我的建议很直接:

  1. 换云镜像。这是最彻底的解法,从下载到进系统只要几分钟。
  2. vCPU控制在2到4个,别贪多。
  3. CPU模型用cortex-a72,别用max。max会开启更多指令集特性,某些特性在TCG下会走慢路径。
  4. 磁盘加cache=writeback参数,减少模拟层的同步开销。
  5. 宿主机上执行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-a72cortex-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.qcow2

virt-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的测试机器,强烈建议做同样的沉淀,省下来的时间够多喝好几杯咖啡了。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/16 9:53:13

Java实验三避坑指南:字符串比较、数组边界与LocalDate日期处理

简介&#xff1a;面向高校C课程分组训练的一份实验资源包&#xff0c;适合作业参考、项目复盘与团队协作练习。资源围绕BJTU程序设计分组训练实验三展开&#xff0c;内含完整可编译的C工程源码与配套实验报告&#xff0c;覆盖基本语法、面向对象设计、数据结构运用、文件读写、…

作者头像 李华
网站建设 2026/9/16 9:52:42

PLC编程思路:从工艺流程到状态逻辑链的工程实践

1. 为什么“PLC编程思路”比“PLC指令怎么写”更重要很多人刚接触PLC&#xff0c;第一反应是翻手册查指令&#xff1a;LD、AND、OR、TON、CTU……背得滚瓜烂熟&#xff0c;一上手写程序却卡在第一步——不知道该从哪开始。我带过三十多个自动化项目新人&#xff0c;八成以上都栽…

作者头像 李华
网站建设 2026/9/16 9:52:05

Sentinel链路流控模式与关闭Context整合实践

1. Sentinel链路流控模式的核心机制解析在分布式系统架构中&#xff0c;流量控制是保障服务稳定性的重要手段。Sentinel作为阿里巴巴开源的流量治理组件&#xff0c;其链路流控模式&#xff08;Link Flow Control&#xff09;能够针对特定调用链路进行精细化控制。而"关闭…

作者头像 李华
网站建设 2026/9/16 9:51:06

hyperframes:用HTML+CSS+CLI实现网页帧级动画控制

1. 项目概述&#xff1a;什么是 hyperframes&#xff1f;它不是“超帧”&#xff0c;而是一套面向现代网页动画的轻量级帧控制范式你最近在 GitHub、前端技术论坛或 CLI 工具文档里频繁看到hyperframes这个词&#xff0c;它既不像 React 那样是框架&#xff0c;也不像 FFmpeg 那…

作者头像 李华
网站建设 2026/9/16 9:49:06

主动悬架LQR控制仿真:从状态空间建模到Simulink验证

简介&#xff1a;面向汽车工程、控制理论与MATLAB/Simulink学习者&#xff0c;压缩包围绕主动悬挂控制器的设计与仿真展开&#xff0c;清晰覆盖车辆动力学模型建立、控制器设计、仿真验证等关键环节。包内共5个文件&#xff0c;包括2个MATLAB脚本、1个Simulink仿真模型、1段视频…

作者头像 李华
网站建设 2026/9/16 9:46:59

企业级Agent效能管理:从评估体系到工作流编排的落地指南

1. 效能管理先导课&#xff1a;从单体脚本到Agent系统的度量危机先讲一个我自己经历过的场景&#xff1a;两三年前&#xff0c;大家做AI应用还是以“单轮调用模型”为主&#xff0c;输入一段文本&#xff0c;模型给一段输出&#xff0c;性能好不好基本看模型选型和Prompt写得好…

作者头像 李华