24.6.使用 FreeBSD 上的 QEMU 虚拟化
QEMU 是一款通用的机器仿真和虚拟化工具,完全开源,由一个庞大且活跃的社区开发,支持 FreeBSD、OpenBSD 和 NetBSD 以及其他操作系统。
根据 QEMU 文档:
QEMU 可以通过多种方式使用。最常见的是系统仿真模式,在该模式下,QEMU 提供了一个完整机器的虚拟模型(包括 CPU、内存和仿真设备),用于运行虚拟机操作系统。在这种模式下,CPU 可以完全仿真,也可以与如
KVM、Xen或Hypervisor.Framework等虚拟化管理程序合作,使虚拟机直接在宿主 CPU 上运行。第二种使用方式是用户模式仿真,在该模式下,QEMU 可以在一种 CPU 上启动为另一种 CPU 编译的进程。在此模式下,CPU 始终为仿真状态。
QEMU 还提供了多个独立的命令行工具,例如 qemu-img(1) 磁盘映像工具,允许用户创建、转换和修改磁盘映像。
QEMU 可以仿真多种体系结构,包括 Arm™、i386、x86_64、MIPS™、s390X、SPARC™(Sparc™ 和 Sparc64™)等。有关 QEMU 系统仿真目标的完整列表,请参阅 QEMU 系统仿真目标,该列表会定期更新。
本节介绍了如何在 FreeBSD 上使用 QEMU 进行系统仿真和用户模式仿真,并提供了 QEMU 命令和命令行工具的使用示例。
24.6.1. 安装 QEMU 软件
QEMU 可以作为 FreeBSD 的一款软件包或在 emulators/qemu 中作为 Port 安装。推荐的安装方法是使用软件包构建,因为它包含了大多数用户需要的合理选项和默认设置。
# pkg install qemu安装软件包时会包含一些依赖项。安装完成后,创建一个指向宿主版本的 QEMU 链接,通常情况下如果宿主系统是 Intel™ 或 AMD™ 64 位系统,命令为:
# ln -s /usr/local/bin/qemu-system-x86_64 /usr/local/bin/qemu作为非 root 用户运行以下命令来测试安装:
% qemu这将打开一个窗口,QEMU 会尝试从硬盘、软盘、DVD/CD 和 PXE 启动。由于尚未设置任何启动映像,因此命令会产生一些错误并以 "No bootable device" 结束,如 图 1 所示。不过,这表明 QEMU 软件已正确安装。

图 1. 没有可引导映像的 QEMU
24.6.2. 虚拟机安装
注意
QEMU 处于非常活跃的开发状态,特性和命令选项可能会在不同版本之间发生变化。本节提供了使用 QEMU 版本 9.0.1(2024 年夏季)开发的示例。若有疑问,请始终查阅 QEMU 文档,特别是 关于 QEMU 页面,该页面包含支持的构建平台、仿真、已弃用功能和已移除功能的链接。
按照以下步骤创建两个名为“left”和“right”的虚拟机。大多数命令可以在没有 root 权限的情况下执行。
创建一个测试环境来与 QEMU 一起使用:
SCRIPTS 目录用于存放启动脚本和实用工具。ISO 目录用于存放客户机 ISO 启动映像。VM 目录是虚拟机映像(
VMs)的存放位置。将最新的 FreeBSD 下载到 ~/QEMU/ISO 目录中:
下载完成后,创建一个简短的链接。该简短链接将在下面的启动脚本中使用。
切换到虚拟机存放位置(~/QEMU/VM)。运行 qemu-img(1) 来为 “left” 虚拟机创建磁盘映像:
QEMU
raw格式旨在提供最佳性能。该格式简单且没有开销,特别适用于高性能或高吞吐量的场景。此格式适用于对性能要求最大化且不需要额外功能(如快照)的情况。以下脚本中使用了此格式来创建 “left” 虚拟机的磁盘映像。另一种格式是
qcow2,它使用 QEMU 的“写时复制”技术来管理磁盘空间。这种技术不需要完整的 15G 磁盘,而是直接由虚拟机管理一个简版磁盘,随着虚拟机写入,磁盘大小会动态增长。此格式支持快照、压缩和加密。此格式适用于开发、测试及需要这些高级功能的场景。下面的 “right” 虚拟机脚本使用了此格式。再次运行 qemu-img(1) 来为 “right” 虚拟机创建一个
qcow2格式的磁盘映像:要查看实际文件大小,可以使用:
使用以下命令为两个虚拟机配置网络。在此示例中,宿主网络接口是
em0。如果有必要,请修改为宿主系统的接口。每次宿主机重启后必须执行这些命令,以便让 QEMU 客户机虚拟机能够进行通信。上述命令创建了两个 tap(4) 设备(
tap0、tap1)和一个 if_bridge(4) 设备(bridge0)。接着,它们将tap设备和本地宿主接口(em0)添加到桥接中,并设置了两个 sysctl(8) 项目,允许普通用户打开 tap 设备。这些命令使虚拟机能够与宿主的网络栈进行通信。切换到 ~/QEMU/SCRIPTS 目录,使用以下脚本启动第一个虚拟机 “left”。该脚本使用了 QEMU 的原始磁盘格式。
技巧
将上述内容保存到一个文件中(例如
left.sh),并只需运行:%/bin/sh left.sh
QEMU 将在一个单独的窗口中启动虚拟机,并按 图 2 中所示引导 FreeBSD ISO。所有命令选项,如 -cpu 和 -boot,均在 QEMU 的手册页 qemu(1) 中有详细描述。

图 2. FreeBSD 启动加载菜单
技巧
如果在 QEMU 控制台窗口中点击鼠标,QEMU 将“抓取”鼠标,如 图 3 所示。按 Ctl+Alt+G 可以释放鼠标。

图 3. 当 QEMU 抓取鼠标时
注意
在 FreeBSD 上,初始的 QEMU 安装可能会稍慢。这是因为模拟器在第一次使用磁盘时会写入文件系统格式和元数据。随后的操作通常会更快。
安装过程中有几个需要注意的要点:
选择使用 UFS 作为文件系统。ZFS 在小内存的环境下性能不佳。
网络配置使用 DHCP。如果本地局域网支持,也可以配置 IPv6。
在添加默认用户时,请确保该用户是 wheel 组的成员。
安装完成后,虚拟机将重启并进入新安装的 FreeBSD 映像。
以 root 用户登录并按以下方式更新系统:
注意
安装成功后,QEMU 将引导已安装的操作系统,而不是安装程序。
注意
QEMU 支持
-runas选项。为了增加安全性,可以在上述脚本中包括 "-runas your_user_name" 选项。详情请参见 qemu(1)。 再次以root用户登录,添加所需的任何软件包。若要在客户机中使用 X Window 系统,请参阅下文的“使用 X Window 系统”部分。
至此,"left" 虚拟机的安装已完成。
要安装 "right" 虚拟机,请运行以下脚本。此脚本包含了 tap1、qcow2 格式、映像文件名、MAC 地址和终端窗口名的修改。如果需要,可以按照上述说明添加 "-runas" 参数。
安装完成后,“left”和“right”虚拟机可以相互通信,并与宿主进行通信。如果宿主机上有严格的防火墙规则,考虑添加或修改规则以允许桥接和 tap 设备之间的通信。
24.6.3. 使用提示
24.6.3.1. 使用 X Window 系统
安装 Xorg 描述了如何设置 X Window 系统。请参考该指南进行初始的 X Window 设置,然后查阅 桌面环境 以了解如何设置完整的桌面环境。
本节演示了 XFCE 桌面环境的使用。
安装完成后,作为常规用户登录,然后输入:
XFCE4 窗口管理器将启动并呈现一款功能齐全的图形桌面,如 图 4 所示。首次启动时,可能需要一分钟才能显示桌面。有关使用详细信息,请参阅 XFCE 网站。

图 4. 两个 QEMU 虚拟机
技巧
为虚拟系统添加更多内存可能会加速图形用户界面。
在这里,“left”虚拟机已经安装了 X Window 系统,而“right”虚拟机仍处于文本模式。
24.6.3.2. 使用 QEMU 窗口
QEMU 窗口作为一个完整的 FreeBSD 控制台,能够像裸机系统一样运行多个虚拟终端。
要切换到另一个虚拟控制台,单击 QEMU 窗口并输入 Alt+**F2 或 Alt+F3。FreeBSD 应该会切换到另一个虚拟控制台。图 5 显示了 "left" 虚拟机在 ttyv3 上显示虚拟控制台的情况。

图 5. 在 QEMU 窗口中切换到另一个虚拟控制台
技巧
当前主机桌面管理器或窗口管理器可能已经为 Alt+F1、Alt+**F2 键序列设置了其他功能。如果是这样,请尝试输入 Ctl+Alt+F1、Ctl+Alt+F2,或其他类似的键组合。查看窗口管理器或桌面管理器文档以了解详细信息。
24.6.3.3. 使用 QEMU 窗口菜单
QEMU 窗口的另一个功能是 View 菜单和缩放控制。最有用的是 Zoom to Fit。当点击此菜单项时,可以通过点击窗口角部控制并调整窗口大小来调整 QEMU 窗口的大小。图 6 显示了在图形模式下调整“left”窗口大小的效果。

图 6. 使用视图菜单中的 Zoom to Fit 选项
24.6.3.4. 其他 QEMU 窗口菜单选项
在 View 菜单中,还可以看到以下选项:
cirrus-vga、serial0和parallel0选项。这些选项允许切换输入/输出到选定设备。
QEMU 窗口中的 Machine 菜单提供了对虚拟机的四种控制:
Pause可暂停 QEMU 虚拟机。这可能对冻结快速滚动的窗口有帮助。Reset会立即将虚拟机重置为冷启动状态。与实际机器一样,除非绝对必要,否则不建议使用此选项。Power Down模拟 ACPI 关闭信号,操作系统将执行优雅的关闭过程。Quit会立即关闭虚拟机电源 — 同样,不建议除非必要时使用此选项。
24.6.4. 向虚拟机添加串行端口接口
为了实现串行控制台,需要在运行 FreeBSD 的虚拟机中插入以下内容:
将此行添加到 /boot/loader.conf 文件中,以启用 FreeBSD 串行控制台的使用。
以下更新后的配置演示了如何在虚拟机上实现串行控制台。运行脚本以启动虚拟机。

图 7. 通过 TCP 启用串行端口
在 图 7 中,串行端口被重定向到主机系统的 TCP 端口,并且 QEMU 监视器等待(wait=on)直到在指定的 localhost 端口发生 telnet(1) 连接。当收到来自另一个会话的连接时,FreeBSD 系统开始启动并查找 /boot/loader.conf 中的控制台指令。通过设置 "console=comconsole",FreeBSD 在串行端口上启动一个控制台会话。QEMU 监视器会检测到这一点,并将该串行端口的字符 I/O 导向主机上的 telnet 会话。系统启动完成后,登录提示将在串行端口(ttyu0)和控制台(ttyv0)上启用。
需要注意的是,这种通过 TCP 的串行重定向是在虚拟机之外进行的。它不与虚拟机中的任何网络进行交互,因此不受任何防火墙规则的限制。可以将其视为连接到实际机器的 RS-232 或 USB 端口的傻终端。
24.6.4.1. 使用串行控制台的注意事项
在串行控制台上,如果调整了窗口大小,可以执行 resizewin(1) 来更新终端大小。
有时可能需要(甚至必须)停止将 syslog 消息发送到控制台(包括 QEMU 控制台和串行端口)。有关将控制台消息重定向到其他位置的详细信息,请参考 syslog.conf(5)。
注意
待 /boot.loader.conf 文件已更新以允许串行控制台,虚拟机将在每次启动时尝试从串行端口启动。确保如上所示启用串行端口,或者更新 /boot/loader.conf 文件以不要求使用串行控制台。
24.6.5. QEMU 用户模式仿真
QEMU 还支持在与主机 CPU 架构不同的体系结构上运行预编译的应用程序。例如,可以在 x86_64 主机上运行 Sparc64 架构的操作系统。下一节将展示这一过程。
24.6.5.1. 在 x86_64 主机上设置 SPARC64 虚拟机
设置与主机架构不同的新虚拟机涉及以下几个步骤:
获取将在虚拟机上运行的软件
为虚拟机创建一个新的磁盘镜像
设置一个新 QEMU 脚本,指定新的架构
执行安装
以下过程使用了 OpenBSD 6.8 SPARC64 软件作为本次 QEMU 用户模式仿真练习的示例。
技巧
并非所有版本的 OpenBSD Sparc64 都能在 QEMU 上运行。已知 OpenBSD 版本 6.8 可用,因此作为本节示例。
从 OpenBSD 存档中下载 OpenBSD 6.8 Sparc64。 在 OpenBSD 下载站点上,仅保留最新版本,需要访问存档以获取过去的版本。
为 Sparc64 虚拟机创建新的磁盘镜像,这与上面的 "right" 虚拟机创建方法类似。在本例中使用 QEMU 的 qcow2 格式:
使用以下脚本设置新的 Sparc64 架构。与上面的示例一样,运行该脚本,然后启动一个新的会话并通过
telnet连接到 localhost 上指定的端口:
注意以下几点:
-boot d选项使 QEMU 从设置为-cdrom ../ISO/install68.iso的 QEMU CDROM 设备启动。如前所述,
telnet服务器选项设置为等待在端口 4410 上接收连接。启动另一个会话并使用 telnet(1) 连接到 localhost 上的 4410 端口。该脚本设置了
-nographic选项,意味着只有串行端口 I/O,没有图形界面。本例中网络未通过 tap(4) / if_bridge(4) 组合设置。这里使用了 QEMU 网络的另一种方法,称为“串行线互联网协议”(SLIRP),有时也称为“用户模式网络”。有关该方法及其他 QEMU 网络方法的文档,请参见 QEMU 网络文档
如果一切设置正确,系统将启动,如 图 8 所示。

图 8. QEMU 在用户模式仿真中从 CDROM 启动 OpenBSD 6.8 Sparc64
安装完成后,修改脚本并将启动参数更改为 -boot c。这将指示 QEMU 从提供的硬盘启动,而不是 CDROM。
安装后的系统可以像其他虚拟机一样使用。然而,虚拟机的底层架构是 Sparc64,而非 x86_64。
技巧
如果系统在 OpenBios 控制台提示
0 >时停止,请输入power-off来退出系统。
图 9 显示了登录已安装系统的 root 用户并运行 uname(1)。

图 9. 在用户模式仿真中从 CDROM 启动 QEMU
24.6.6. 使用 QEMU 监控器
QEMU 监控器 用于控制正在运行的 QEMU 模拟器(虚拟机)。
通过使用监控器,可以:
动态地移除或插入设备,包括磁盘、网络接口、CD-ROM 或软盘
冻结/解冻虚拟机,并将其状态保存或恢复到磁盘文件中
收集有关虚拟机和设备状态的信息
实时更改设备设置
以及许多其他操作。
监控器的最常见用途是检查虚拟机的状态,并添加、删除或更改设备。一些操作,如迁移,仅在支持的虚拟化加速器(如 KVM、Xen 等)下可用,在 FreeBSD 主机上不受支持。
在使用图形桌面环境时,最简单的使用 QEMU 监控器的方法是启动 QEMU 时使用 -monitor stdio 选项。
这将在终端窗口中生成一个新的提示符 (qemu),如 图 10 所示。

图 10. QEMU 监控器提示符和“stop”命令
图中还显示了在 FreeBSD 启动序列中使用 stop 命令冻结系统。系统将保持冻结状态,直到在监控器中输入 cont 命令。
24.6.6.1. 向虚拟机添加新磁盘
要向运行中的虚拟机添加新磁盘,首先需要准备磁盘,如下所示:
图 11 显示了向虚拟机添加新磁盘所需的监控器命令序列。待使用监控器中的 device_add 命令添加了设备,它将在 FreeBSD 系统控制台中显示(图中的下半部分)。此时可以根据需要配置磁盘。
请注意,如果需要在虚拟机重启后使用新磁盘,必须将其添加到启动脚本中。

图 11. 使用 QEMU 监控器命令添加新磁盘
24.6.6.2. 使用 QEMU 监控器管理快照
QEMU 文档在使用术语 快照 时描述了几个类似的概念。命令行上有 -snapshot 选项,它指的是使用一个磁盘或磁盘的一部分来包含设备的副本。然后是监控器命令 snapshot_blkdev 和 snapshot_blkdev_internal,它们描述了实际的复制块设备的操作。最后,还有监控器命令 savevm、loadvm 和 delvm,它们指的是创建并保存、加载或删除整个虚拟机的副本。结合后者,监控器的 info snapshots 命令列出了最近的快照详情。
本节将重点介绍创建、保存和加载完整的虚拟机镜像,并使用 快照 这一术语。
首先,从头开始重新创建“左”虚拟机,这次使用 qcow2 格式。
安装完成后,重新启动虚拟机,这次使用 -monitor stdio 选项来启用监控器。
为了演示快照,可以使用以下步骤:
从头安装 FreeBSD
准备环境并使用
savevm监控器命令创建快照安装几个软件包
关闭系统
重新启动一个裸 QEMU 实例,并使用监控器命令
loadvm恢复虚拟机观察恢复后的虚拟机没有安装任何软件包
在“准备环境”步骤中,在一个独立的虚拟控制台(ttyv1)中启动一个 vi(1) 编辑会话,模拟用户活动。如果需要,可以启动其他程序。快照应该记录在创建快照时所有正在运行的应用程序的状态。
图 12 显示了全新安装的 FreeBSD 系统,尚未安装任何软件包,并且在 ttyv1 上单独显示了编辑会话。当前, vi(1) 编辑器处于 insert 模式,打字员正在输入“broadcast”一词。

图 12. 第一次快照之前的 QEMU 虚拟机
要生成快照,请在监控器中输入 savevm。确保为其指定标签(例如 original_install)。
接下来,在主控制台窗口中安装一个软件包,例如没有依赖关系的 zip(1)。完成后,重新进入监控器并创建另一个快照(snap1_pkg+zip)。
图 13 显示了上述命令的结果以及 info snapshots 命令的输出。

图 13. 使用监控器命令进行快照
重新启动系统,在 FreeBSD 启动之前,切换到监控器并输入 stop。虚拟机将停止。
输入 loadvm 和之前使用的标签(此处为 original_install)。
立即,虚拟机屏幕将切换到执行 savevm 命令时的准确时刻。请注意,虚拟机仍然处于停止状态。
输入 cont 启动虚拟机,切换到 ttyv1 上的编辑会话,并在键盘上输入一个字母。编辑器仍然处于插入模式,应该相应地响应。快照时运行的任何其他程序应该没有受到影响。
上述步骤展示了如何创建快照、修改系统,然后通过恢复之前的快照来“回滚”。
默认情况下,QEMU 将快照数据存储在与镜像相同的文件中。使用 qemu-img(1) 查看快照列表,如下所示,见 图 14。

图 14. 使用 qemu-img(1) 检查快照
24.6.7. 使用 QEMU USB 设备
QEMU 支持创建虚拟 USB 设备,这些设备由映像文件提供支持。它们是虚拟 USB 设备,可以像真实 USB 设备一样进行分区、格式化、挂载和使用。
此配置包括一个 -drive 规范,指定了 id=usbstick、raw 格式和一个映像文件(必须使用 qemu-img(1) 创建)。下一行包含 -device usb-ehci 规范,指定一个 USB EHCI 控制器,并指定 id=ehci。最后,-device usb-storage 规范将上述驱动与 EHCI USB 总线连接起来。
当系统启动时,FreeBSD 会识别到一个 USB 集线器,添加附加的 USB 设备,并将其分配为 da0,如图 15 所示。

图 15. QEMU 创建的 USB 集线器和大容量存储设备
该设备已准备好,可以使用 gpart(8) 进行分区,并使用 newfs(8) 进行格式化。由于 USB 设备由 qemu-img(1) 创建的文件提供支持,写入设备的数据会在重启后保留。
24.6.8. 通过直通使用主机 USB 设备
QEMU USB 直通支持在 9.0.1 版本(2024 年夏季)中列为实验性功能。以下步骤展示了如何使用挂载在主机上的 USB 闪存驱动器。
更多信息和示例,请参见:
图 16 的上部分显示了 QEMU 监视器命令:
info usbhost显示主机系统上所有 USB 设备的信息。找到所需的 USB 设备并记下该行中的两个十六进制值。(在下面的示例中,主机 USB 设备是 Memorex Mini,vendorid 为 0718,productid 为 0619。)在下面的device_add步骤中使用info usbhost命令显示的两个值。device_add将 USB 设备添加到虚拟机。

图 16. QEMU 监视器命令访问主机上的 USB 设备
如前所述,device_add 完成后,FreeBSD 内核会识别到新的 USB 设备,如图下部分所示。
在 图 17 中,展示了如何使用新设备。

图 17. 通过直通使用主机的 USB 设备
如果 USB 设备格式化为 FAT16 或 FAT32 文件系统,则可以使用 mount_msdosfs(8) 将其挂载为 MS-DOS™ 文件系统,如示例所示。然后将 /etc/hosts 文件复制到新挂载的驱动器上,并对文件进行校验和验证其完整性。然后使用 umount(8) 卸载设备。
如果 USB 设备格式化为 NTFS,则需要安装 fusefs-ntfs 包并使用 ntfs-3g(8) 访问该设备:
根据实际硬件修改上述设备标识符。有关 NTFS 文件系统操作的更多信息,请参阅 ntfs-3g(8)。
24.6.9. QEMU 在 FreeBSD 上的总结
如上所述,QEMU 支持多种不同的虚拟化加速器。
QEMU 支持的 虚拟化加速器 包括:
在 Linux 上支持 64 位 Arm、MIPS、PPC、RISC-V、s390x 和 x86 的
KVM在 Linux 上作为 dom0 支持 Arm、x86 的
Xen在 MacOS 上支持 x86 和 Arm(仅 64 位)的
Hypervisor Framework (hvf)在 Windows 上支持 x86 的
Windows Hypervisor Platform (whpx)在 NetBSD 上支持 x86 的
NetBSD Virtual Machine Monitor (nvmm)在 Linux 和其他 POSIX 系统、Windows、MacOS 上支持 Arm、x86、Loongarch64、MIPS、PPC、s390x 和 Sparc64 的
Tiny Code Generator (tcg)
本节中的所有示例都使用了 Tiny Code Generator (tcg) 加速器,因为这是当前在 FreeBSD 上支持的唯一加速器。
最后更新于