把Ubuntu 24.04 LTS当成宿主机,用KVM跑一个macOS 10.x虚拟机,听起来简单,实际操作里藏着不少和Windows/Linux虚拟机完全不一样的坑。我最近刚把整套流程重新走了一遍,从环境检查到启动安装,再到驱动和性能调优,折腾出来的方案基本可以照着抄。这篇就当一次完整的执行记录,顺便把之前踩过的坑一并整理出来。
很多朋友问我,为什么放着现成的VirtualBox或VMware不用,非要在Ubuntu上折腾KVM/QEMU。答案很简单:macOS对虚拟化层的兼容要求很挑剔,KVM加QEMU这套组合虽说配置门槛高,但一旦跑通,性能和灵活性都很可观。而且Ubuntu 24.04 LTS对KVM的支持很成熟,配合libvirt管理,后面做快照、自动启动都很顺手。
下面我会按自己实际操作顺序来写,不会跳过关键细节。前置条件、镜像准备、启动脚本、安装流程、常见问题都会覆盖到,部分内容属于拓展玩法,适合已经跑通基础虚拟机的朋友继续往下看。
1. 项目整体设计与方案选型
1.1 为什么选择KVM/QEMU这条路
安装macOS虚拟机,市面上的路径无非是VirtualBox、VMware、KVM/QEMU,还有ESXi上的Mac补丁方案。VirtualBox安装简单,但macOS图形性能和磁盘性能一直不理想,而且新版VirtualBox对macOS系统版本的兼容支持越来越保守。VMware Workstation在Windows上跑macOS也能跑,但官方并不直接支持,需要手动改引导参数,跨版本升级时容易失效。
相比之下,KVM/QEMU是Linux原生的虚拟化方案。KVM负责把CPU的硬件虚拟化能力交给虚拟机,QEMU负责模拟主板、磁盘、网卡、显卡这些设备。由于KVM是内核模块,虚拟机的CPU指令基本是原生执行的,所以CPU性能损失很小。再加上QEMU支持透传物理设备,只要硬件支持,甚至可以给macOS分配独立显卡,这玩法是其他桌面虚拟化软件很难实现的。
当然缺点也很明显:配置项太多,参数错误就直接黑屏或重启,排错需要一点耐心。但这个缺点完全能用成型脚本模板规避,只要理解了参数含义,后面调优就很有底气。
1.2 “拓展”到底拓展在哪里
这个标题里的“拓展”并不是说用额外工具绕过什么限制,而是指在基础安装之上,把虚拟机的磁盘、网络、显示、快照管理、硬件加速这些维度全部扩展出来。基础版本可能只需要能开机进桌面,拓展版本要考虑的是日常可不可用。
磁盘层面,从单一qcow2镜像扩展出raw备份、快照链和跨主机迁移。网络层面,从默认的用户态网络扩展出桥接模式,让虚拟机像局域网里的独立设备一样被访问。显示层面,从基本VGA输出扩展到virtio-gpu,或者直接透传物理显卡。管理层面,从命令行qemu启动扩展成libvirt守护进程托管,用virsh就能完成开机、关机、打快照。
这些拓展能力才是KVM方案对比桌面虚拟化软件的核心优势。我会在后面的实操章节里,把每一项需要修改的地方指出来。
1.3 硬件与软件前提条件
先别急着敲命令,你的CPU必须支持虚拟化。Intel处理器需要VMX,AMD处理器需要SVM,这个在现代CPU上基本都有,但有些主板的BIOS默认关闭,需要在开机时进入固件设置打开。
确认方法是在终端执行:
grep -E "(vmx|svm)" /proc/cpuinfo如果有输出,说明CPU虚拟化指令已经可用。再检查一下KVM设备节点:
ls /dev/kvm如果能看到/dev/kvm,代表KVM模块已经加载。看不到的话,先尝试加载模块:
sudo modprobe kvm sudo modprobe kvm_intel # Intel CPU sudo modprobe kvm_amd # AMD CPUUbuntu 24.04 LTS的默认内核已经带了KVM相关模块,绝大多数情况下不会有问题。软件方面,需要安装QEMU、libvirt和OVMF固件。OVMF是UEFI固件,macOS引导依赖UEFI环境,这一步不能省略。
2. 宿主机环境准备与虚拟化基础
2.1 安装系统依赖包
在干净的Ubuntu 24.04 LTS上,直接执行:
sudo apt update sudo apt install -y qemu-system-x86 qemu-utils libvirt-daemon-system libvirt-clients ovmf virt-manager dmg2img解释一下这几个包的作用:
qemu-system-x86:QEMU系统模拟器,提供x86_64虚拟机的核心运行环境。qemu-utils:包含qemu-img、qemu-io等磁盘工具,用来创建和转换镜像。libvirt-daemon-system和libvirt-clients:libvirt守护进程和管理工具,后面管理虚拟机肯定用得上。ovmf:UEFI固件,macOS需要UEFI方式引导,不能用传统BIOS。virt-manager:图形化管理工具,虽然我们主要用命令行,但偶尔看一眼虚拟机的运行状态很方便。dmg2img:把macOS的dmg磁盘镜像转换成QEMU能识别的格式。
这里有个容易踩的坑:很多人会忘记装OVMF,结果QEMU启动时没有UEFI固件,直接提示找不到可引导设备。Ubuntu 24.04的OVMF包路径通常是/usr/share/OVMF/OVMF_CODE_4M.fd,后面写启动脚本时要用到。
2.2 启动并配置libvirt守护进程
装好之后,把当前用户加入kvm和libvirt组,避免每次都用sudo执行命令:
sudo usermod -aG kvm $USER sudo usermod -aG libvirt $USER重新登录或者执行newgrp kvm,然后启用libvirt服务:
sudo systemctl enable --now libvirtd用virsh uri确认libvirt连接是否正常。如果输出类似qemu:///system,说明守护进程正常。有人喜欢直接用qemu-system-x86_64命令行裸跑,不用libvirt,这样也可以,但后面如果想用virsh做快照或开机自启,还是建议把配置迁移到libvirt里。这一步先不着急,基础跑通之后再迁移也不迟。
2.3 准备目录结构和固件
我习惯把macOS虚拟机的相关文件统一放在一个目录下,方便管理:
mkdir -p ~/kvm-macos/efi cd ~/kvm-macosefi目录用来存放OpenCore引导文件。OpenCore是一个开源引导加载器,因为macOS的启动流程和普通x86系统不太一样,原生QEMU的EFI固件没法直接引导macOS,必须先经过OpenCore把系统环境伪装成苹果硬件需要的样子。
这里要注意:OpenCore的版本选择和macOS版本有关系。macOS 10.x系列建议使用兼容10.15及更早版本的OpenCore版本,太新的版本反而可能因为APFS模块差异导致引导失败。具体版本号不用死记,遇到引导卡住再去调整就行。
3. 镜像准备与启动脚本设计
3.1 准备macOS安装镜像
macOS的官方安装包是.app格式,里面包含InstallESD.dmg或者BaseSystem.dmg。QEMU没法直接启动dmg,需要转换成raw或者qcow2格式。
在Linux下,我一般先用工具从官方安装器里解出恢复镜像,再转换成QEMU需要的格式。很多macOS虚拟机教程会提供已经制作好的BaseSystem镜像,但我不建议直接用来源不明的镜像,因为无法保证镜像被动过手脚。靠谱做法是在一台mac电脑上从系统更新里下载安装器,然后把里面的BaseSystem.dmg拷贝出来。如果没有mac电脑,也可以从苹果官方的软件下载入口拿到包含安装器的dmg。
拿到BaseSystem.dmg之后,先转换格式:
dmg2img -i BaseSystem.dmg -o BaseSystem.img再用qemu-img压缩成qcow2,可以节省不少磁盘空间:
qemu-img convert -f raw -O qcow2 BaseSystem.img BaseSystem.qcow2实际上BaseSystem只是一个恢复模式系统,安装的时候它会从网络或本地安装源拉取完整系统。所以这个镜像一般只有500MB左右,非常小巧。
3.2 创建macOS虚拟磁盘
接下来给macOS本身创建一块硬盘:
qemu-img create -f qcow2 macos.qcow2 60G大小按需求调整,建议至少40G,因为macOS系统本身占20G左右,加上Xcode或开发工具会显得紧张。我这边给到60G,日常做编译测试够用。
这里说明一下为什么要用qcow2而不是raw。qcow2支持按需分配,刚创建时不会占满60G,只有虚拟机实际写入时才增长。它还支持快照,随时可以回滚到某一个时间点。缺点是性能比raw略低,但通过后面调优可以弥补。对大文件读写有极致需求的,可以创建raw格式,但注意备份时空间会吃紧。
3.3 制作OpenCore引导盘
OpenCore需要放在一个FAT分区里,QEMU才能识别。创建一个64MB的小磁盘镜像,格式化后再把OpenCore的EFI目录复制进去。
创建引导盘镜像:
qemu-img create -f raw OpenCore.img 64M mkfs.vfat OpenCore.img挂载后复制文件:
mkdir /tmp/efi-mount sudo mount -o loop OpenCore.img /tmp/efi-mount sudo cp -r OpenCore/EFI /tmp/efi-mount/ sync sudo umount /tmp/efi-mount这里OpenCore/EFI目录指你下载或编译好的OpenCore文件。如果只是想快速跑通,也可以直接找一个针对macOS虚拟化的现成EFI配置改一改,但最好还是理解一下目录结构,方便后面排错。
3.4 编写QEMU启动脚本
现在到了最关键的部分。我习惯把启动命令写成shell脚本,方便反复调整。下面这份是我在Ubuntu 24.04上用KVM跑macOS 10.15的模板:
#!/bin/bash qemu-system-x86_64 \ -machine q35,accel=kvm \ -cpu host,hv_vendor_id=0x00000000,host-phys-bits=on \ -smp 4 \ -m 8G \ -drive if=pflash,format=raw,readonly=on,file=/usr/share/OVMF/OVMF_CODE_4M.fd \ -drive if=pflash,format=raw,file=OVMF_VARS.fd \ -drive if=virtio,file=BaseSystem.qcow2,format=qcow2,media=cdrom \ -drive if=virtio,file=macos.qcow2,format=qcow2 \ -drive if=virtio,file=OpenCore.img,format=raw \ -device virtio-net-pci,netdev=net0 \ -netdev user,id=net0 \ -device qxl-vga,vram_size=131072 \ -usb -device usb-tablet \ -global ICH9-LPC.acpi-pci-hotplug-with-bridge-support=off这个脚本有几个地方值得展开说。
-machine q35,accel=kvm,q35是Intel ICH9芯片组的现代化主板模型,比老式的i440fx更适合macOS。ICH9-LPC上的acpi热插拔参数被关闭,是因为macOS 10.15对ACPI热插拔的处理有兼容问题,不加上这个参数,安装阶段很容易自动重启。
-cpu host,hv_vendor_id=0x00000000,host-phys-bits=on,直接把宿主CPU指令集透传进去,性能最高。hv_vendor_id是给Hyper-V用的,设成全零可以避免部分macOS版本误判是在虚拟机里。如果你遇到macOS“禁止”符号或开机五国语言崩溃,很大概率是CPU型号暴露了,改成-cpu Penryn,vendor=GenuineIntel试试。
-drive if=pflash,...,把OVMF固件当作主板上的Flash设备加载。第一块是只读的UEFI代码,第二块是可写的变量存储。每次升级固件后最好重新创建一份干净的OVMF_VARS.fd,不然旧的变量会残留。
-drive if=virtio,file=BaseSystem.qcow2,media=cdrom,这是把恢复镜像模拟成光盘来引导。这里用virtio接口主要是读取性能好,不过macOS恢复环境对虚拟光驱的兼容性也还可以。如果你启动后看不到安装盘,改成if=ide再试。
-device qxl-vga,QXL显卡,这是KVM下相对成熟的虚拟GPU。macOS对qxl驱动支持不太好,但至少能进入安装界面并调整分辨率。追求原生图形性能的话,后续可以尝试virtio-gpu或物理显卡透传,不过那需要更多改动。
-device usb-tablet,模拟USB方式获取鼠标坐标。不加这个,鼠标在图形界面里可能出现漂移或只能在一个角落移动,尤其用VNC连接管理虚拟机时特别明显。
OpenCore引导盘放在第三块virtio盘上。QEMU启动时UEFI固件会从这块盘上找到EFI shell,进而执行OpenCore的引导逻辑。注意OpenCore.img要被格式化为可引导的FAT分区,并且EFI目录里要有BOOT/BOOTx64.efi。
写完之后给脚本加执行权限:
chmod +x start-macos.sh再运行脚本。如果一切正常,QEMU窗口会进入OpenCore引导界面。首次引导需要选择“macOS Base System”这个选项,如果OpenCore配置了自动扫描启动项,也可能直接进入安装界面。
4. 安装过程与关键配置
4.1 从OpenCore进入macOS安装器
第一次启动,OpenCore界面可能比较简陋。使用方向键选择带macOS字样的启动项,回车后等待几分钟。这里有个经验:macOS恢复环境启动很慢,尤其是首次,因为它要初始化APFS卷和缓存文件,在笔记本上甚至可能等三分钟。不要一看屏幕没动静就关掉,可以观察CPU占用,如果宿主机的qemu进程在持续吃CPU,就说明系统正在进行初始化。
进入macOS实用工具界面后,先打开“磁盘工具”,把之前那块60G的虚拟磁盘抹掉,格式选APFS,分区图类型选GUID。不抹掉磁盘的话,安装器会提示无法安装到当前设备。抹完之后退出磁盘工具,选择“安装macOS”,安装源就指向那个虚拟光驱里的恢复镜像。
安装过程会自动重启几次。这里最常见的现象是:第一次重启后,OpenCore不再显示安装选项,而是直接进入硬盘里的临时系统。如果卡在苹果进度条上,尤其是进度条走了一段然后重启,优先检查-global ICH9-LPC.acpi-pci-hotplug-with-bridge-support=off参数有没有加上。这个参数是我在多次重启崩溃后加上的,实测能解决大部分安装期无限重启问题。
4.2 安装完成后的驱动和显示调整
装完进入桌面后,基本系统能跑,但有几个地方需要手动处理。首先是分辨率,QXL显卡默认只有1024x768或者更低。可以找到“系统偏好设置”里的“显示器”调整,如果没有合适分辨率,说明QXL驱动没完全加载。这个阶段不要执着于高分辨率,能用就行。非要高分辨率的话,可以用软件修改OpenCore配置文件里的NVRAM,添加自定义boot-args,比如-v调试模式或-disablegfxfirmware,但这部分比较繁琐,建议等系统稳定后再玩。
网络方面,我在脚本里用的是用户态网络-netdev user,这种模式下虚拟机可以访问外网,但宿主机访问虚拟机需要端口映射。如果只是安装完更新系统,这个模式完全够用。桥接网络的配置我会在拓展章节细说。
磁盘方面,macOS对virtio-blk原生支持有限,这也是为什么我没有直接用virtio接口挂载系统盘,而是用了if=virtio给光驱,但系统盘其实也用virtio接口?老实说,在macOS 10.15下,QEMU的virtio-blk需要额外驱动,不装驱动可能识别不到磁盘。我在脚本里给系统盘写的是if=virtio,这可能有问题。实际稳妥做法是系统盘也用ide-hd。
让我重新修正启动脚本里磁盘部分,避免读者照抄翻车:
-device ide-hd,drive=system_disk,bus=ide.0 \ -drive id=system_disk,file=macos.qcow2,format=qcow2,if=none \ -device ide-hd,drive=base_system,bus=ide.1 \ -drive id=base_system,file=BaseSystem.qcow2,format=qcow2,if=none,media=cdrom这样macOS把两块盘都认成IDE设备,兼容性最好,只是性能相对弱一些。后期如果安装了virtio驱动,再改回virtio接口也不迟。我想说的是,网上很多脚本为了省事把盘挂成virtio,没加驱动的情况下能安装纯属运气。宁可先稳定,再提速。
4.3 性能调优与资源分配
macOS虚拟机跑起来之后,CPU和内存的分配需要结合宿主机实际资源。-smp 4代表4个vCPU,-m 8G代表8G内存。宿主机是16G内存的话,这个分配合理;如果是8G内存,建议降到4G。CPU核数和线程数也要给QEMU留点余量,别全部分配给虚拟机,否则宿主机操作会卡顿。
磁盘性能是最大的瓶颈。qcow2格式写放大明显,频繁读写时CPU占用偏高。一个简单优化是给qcow2指定预分配模式,创建镜像时加-o preallocation=metadata能减少初次写入延迟。大数据量编译场景可以用raw格式,但需要留意磁盘空间。内存足够大的话,还可以给QEMU开启-mem-prealloc,让虚拟机内存提前分配,减少运行期page fault。
CPU调优上,-cpu host已经不错,可以加-overcommit cpu-pm=on允许CPU电源管理,让虚机在闲置时降低频率。另外如果宿主CPU支持NUMA,可以查看自己的拓扑再决定是否需要绑定vCPU到特定物理核心,这个属于进阶话题,普通用户不必纠结。
5. 常见问题与排查技巧实录
5.1 启动即崩溃或反复重启
这是最多人遇到的情况,基本集中在以下几个原因。
- 没有加
-global ICH9-LPC.acpi-pci-hotplug-with-bridge-support=off,导致macOS在启动阶段检测到PCI热插拔能力后触发ACPI panic。解决方法是补上这个参数。 - CPU参数不合适。Intel和AMD的KVM都建议用
-cpu host,但如果宿主CPU太新,macOS 10.15的内核可能不认识,此时改用-cpu Penryn或-cpu Nehalem并加上vendor=GenuineIntel。 - OVMF固件路径错误。检查
/usr/share/OVMF/下是否存在OVMF_CODE_4M.fd。部分Ubuntu包版本会安装OVMF_CODE.fd而没有4M版本,需要相应调整路径。
5.2 提示“不能安装到这台电脑”
这个提示一般是固件信息没伪装好。macOS安装器会检查主板是否为苹果认可的硬件,OpenCore其实已经处理了绝大部分伪装,但如果你的OpenCore配置里缺少SystemProductName、SystemSerialNumber这些SMBIOS字段,或者字段格式不完整,安装器就会跳出这个错误。重新提取一份完整的OpenCore配置,或者使用现成针对QEMU的模板,问题一般能解决。
5.3 鼠标漂移或点击偏移
QEMU默认模拟PS/2鼠标,在macOS下兼容性很差。解决办法就是加-device usb-tablet。KVM窗口模式下,这个参数能把鼠标坐标直接映射到虚拟机桌面,不需要额外驱动。如果加了还是漂移,检查OpenCore的UsbKbDxe或UsbMouseDxe驱动有没有被加载。
5.4 网络不通或网速极慢
用户态网络模式下,虚拟机的IP是由QEMU内建的DHCP分配的,默认网段是10.0.2.0/24。如果你在macOS里看到没IP,检查-netdev user是否配置正确。如果网络时通时断,可以尝试换用e1000网卡:
-device e1000,netdev=net0macOS对e1000的支持比virtio-net稳定。当然e1000的性能上限不高,适合测试环境。要获得更好的性能且不想装驱动,可以尝试vmxnet3,但需要安装VMware提供的驱动,这个就比较折腾了。
5.5 常见问题速查表
| 现象 | 可能原因 | 排错步骤 |
|---|---|---|
| 开机黑屏无任何输出 | OVMF固件未配置或路径错误 | 检查pflash参数和OVMF文件是否存在 |
| 启动界面出现“禁止”符号 | CPU型号未正确伪装 | 换用Penryn或Nehalem模型,添加vendor=GenuineIntel |
| 安装进度条走到一半重启 | ACPI热插拔冲突 | 添加ICH9-LPC acpi关闭参数 |
| 无法抹掉磁盘 | 分区表类型不对 | 磁盘工具选择GUID分区图,格式选APFS |
| 鼠标漂移 | 缺少USB坐标设备 | 添加usb-tablet设备 |
| 网络无法获取IP | 网卡型号兼容问题 | 改用e1000,检查user网络参数 |
| 声音没有输出 | 音频设备未配置 | 添加-device intel-hda -device hda-duplex |
这里的音频配置,我补充一下。macOS 10.15对Intel HDA的支持还可以,在QEMU里加上-device intel-hda -device hda-duplex就能获得声音,但延迟可能略高。如果声卡导致开机卡顿,可以先去生化掉相关驱动,最后再弄音频,不影响安装。
6. 进阶玩法:快照、桥接与自动管理
6.1 用libvirt托管虚拟机
跑通基础命令行后,下一步是让libvirt接管这台虚拟机。这样你就不用在脚本里裸敲QEMU命令,而是通过virsh进行生命周期管理。virsh shutdown、virsh snapshot-create-as、virsh autostart都很方便。
从现有QEMU命令行迁移到libvirt有现成工具,比如virsh domxml-from-native:
virsh domxml-from-native qemu-argv ./start-macos.sh > macos.xml生成XML后,编辑检查一下,再执行:
virsh define macos.xml virsh start macos需要注意的是,libvirt访问OVMF和磁盘文件的权限要正确,通常需要把文件和目录加到/etc/libvirt/qemu.conf里的user和group配置下,或者直接使用qemu:///system连接。
6.2 快照与备份策略
qcow2镜像的最大优势就是支持内置快照。在虚拟机关机状态下,运行:
virsh snapshot-create-as macos install-clean "刚装完系统"之后如果系统搞坏了,直接用:
virsh snapshot-revert macos install-clean就能恢复到刚装完的状态。注意,快照会占用磁盘空间,尤其是频繁快照之后,qcow2文件会不断膨胀。定期清理不需要的快照,或者把镜像整体导出备份,是最好的习惯。我个人每个月会导出一份干净的qcow2到外置盘,防止宿主系统故障连带丢失虚拟磁盘。
6.3 桥接网络让虚拟机成为独立节点
用户态网络虽然简单,但宿主机访问虚拟机里的服务要设置端口映射,不够直观。想让macOS虚拟机获得局域网独立IP,可以把QEMU网络改到桥接模式。
Ubuntu 24.04 LTS上可以用NetworkManager创建网桥。我的做法是:
nmcli connection add type bridge ifname br0 con-name br0 nmcli connection add type ethernet con-name bridge-slave ifname enp3s0 master br0把enp3s0替换成你的物理网卡名。建好后QEMU命令改成:
-netdev bridge,id=net0,br=br0这样macOS虚拟机会直接从局域网路由器获取IP。桥接模式对虚拟机网络性能提升明显,也不会有NAT端口限制,适合在里面跑测试服务。
6.4 开机自动启动
虚拟机做完快照、桥接网络之后,还可以设置宿主开机自动启动。用libvirt管理时最简单:
virsh autostart macos这样每次宿主机启动,虚拟机就会自己起来。不过macOS虚拟机的自动启动建议延迟几分钟,等宿主服务稳定后再启动,毕竟QEMU需要访问磁盘和网络资源。可以在libvirt里配置<bootloader>延时,或者干脆在系统服务里写个ExecStartPre睡眠。我个人不太建议在资源紧张的机器上自动启动重型虚拟机,容易造成宿主启动时负载过高。
写在最后的几点体会
踩过这一轮Ubuntu 24.04 KVM装macOS的坑,最强烈的感受是:macOS虚拟机不像Linux虚拟机那么“皮实”,很多参数都要小心翼翼。尤其是CPU型号和ACPI配置,差一行参数就可能完全无法启动。建议新手先用模板跑通一次,再去改细节,不要一上来就追求显卡透传和声卡。
另外,macOS虽然能在KVM上运行,但它毕竟不是为开放硬件设计的系统。虚拟机的镜像文件要妥善保管,不要随意分发,自己也做好备份。日常使用中,我发现KVM下macOS的CPU性能非常接近原生,但磁盘和图形还是有差距。如果单纯是为了测试Xcode编译或者Safari渲染,这套方案足够用;如果想玩大型游戏,还是别指望虚拟机了。
最后分享一个小技巧:当你排查到怀疑是OpenCore配置导致问题时,不要在虚拟机上反复试。直接把OpenCore.img挂载到宿主机,修改里面的config.plist,保存后重新挂载回QEMU,比在虚拟机里用编辑器快得多。这个小流程救了我很多次。