2. 虚拟化与设备直通基础
在讨论设备直通与 IOMMU 之前,必须先建立虚拟化的基本心智模型:虚拟机并不是“更快的模拟器”,而是由 CPU 硬件辅助、Hypervisor 调度、内存与设备资源被重新划分后形成的一台逻辑计算机。设备直通之所以有价值,正是因为它绕开了传统虚拟化中“设备访问必须经过 Hypervisor 软件模拟”的瓶颈。理解这一章,是后续配置 VT-d/AMD-Vi、VFIO、SR-IOV 与多 OS 直通工程的前提。
一、虚拟化原理:从“特权指令”到“硬件辅助”
虚拟化的核心目标,是让多个操作系统实例共享同一套物理硬件,同时彼此隔离、互不干扰。早期 x86 架构并不支持虚拟化,因为某些敏感指令在用户态执行时不会触发异常,Hypervisor 无法可靠拦截。于是出现了两种思路:一是二进制翻译,在运行时扫描并替换敏感指令;二是半虚拟化,要求 Guest OS 主动修改内核,把敏感操作换成对 Hypervisor 的调用(hypercall)。
现代虚拟化则依赖 CPU 提供的硬件辅助能力:Intel VT-x 与 AMD-V 引入了根模式与非根模式,Guest 运行在非根模式,遇到敏感指令或特定事件时自动触发 VM Exit,由 Hypervisor 处理后再 VM Entry 返回。内存方面,EPT(Intel)与 NPT(AMD)实现二级地址转换,让 Guest 物理地址到宿主物理地址的映射由硬件完成,避免影子页表的频繁同步开销。
二、Hypervisor 类型:Type 1 与 Type 2
Hypervisor(虚拟机监视器)按运行位置可分为两类。Type 1 直接运行在裸金属上,如 VMware ESXi、Microsoft Hyper-V、Xen、KVM(严格说 KVM 是 Linux 内核模块,属于 Type 1 的宿主型实现)。Type 2 运行在宿主操作系统之上,如 VirtualBox、VMware Workstation。两者在设备直通场景中的差异非常明显:Type 1 通常能更直接地控制 IOMMU 与中断重映射,延迟更低;Type 2 需要经过宿主内核转发,配置更简单但性能与隔离性受限。
| 对比维度 | Type 1(裸金属/宿主型) | Type 2(宿主应用型) |
|---|---|---|
| 典型代表 | ESXi、Xen、KVM、Hyper-V | VirtualBox、VMware Workstation |
| 设备直通支持 | PCIe Passthrough、SR-IOV、VFIO 成熟 | 有限,常依赖 USB 直通或实验性 PCI 直通 |
| IOMMU 控制 | 可直接绑定 DMA 重映射与中断重映射 | 需宿主 OS 暴露,隔离粒度较粗 |
| 典型延迟 | 低,接近原生 | 较高,受宿主调度影响 |
| 适用场景 | 生产虚拟化、多 OS 直通、DPDK/GPU 直通 | 开发测试、桌面体验、轻量隔离 |
三、全虚拟化与半虚拟化:设备视角的差异
全虚拟化(Full Virtualization)不要求 Guest 修改内核,Guest 以为自己运行在真实硬件上,所有敏感操作由 Hypervisor 透明拦截与模拟。半虚拟化(Paravirtualization)则要求 Guest 安装特定驱动,主动与 Hypervisor 协作。以设备 I/O 为例:全虚拟化下,Guest 看到的是一块模拟的 e1000 网卡,每次收发包都要触发 VM Exit,由 QEMU 模拟寄存器读写,性能损耗大;半虚拟化下,Guest 使用 virtio 驱动,通过共享内存环(virtqueue)批量提交请求,Hypervisor 只需处理通知,效率显著提升。
但 virtio 仍然是“软件路径”:数据要从 Guest 内存拷贝到宿主,再交给真实驱动。设备直通则更进一步,把物理 PCIe 设备直接分配给 Guest,让 Guest 原生驱动直接操作硬件寄存器与 DMA,几乎消除 Hypervisor 在数据路径上的参与。这也是 GPU、NVMe、高速网卡直通时性能接近裸机的原因。
四、设备直通的定义与价值
设备直通(Device Passthrough),又称 PCIe Passthrough,是指把宿主上的一个物理 PCIe 设备(或 SR-IOV 虚拟功能 VF)直接分配给某个虚拟机,使 Guest 内的原生驱动能够直接访问该设备的配置空间、MMIO 寄存器与 DMA 引擎。Hypervisor 不再模拟该设备,只负责在设备分配、DMA 重映射和中断投递上做安全隔离。
它的价值主要体现在三个方面:
- 性能接近原生:消除模拟层与数据拷贝,GPU 渲染、NVMe 高 IOPS、25/100G 网卡转发等场景收益显著。
- 功能完整:模拟设备往往只覆盖基础功能,直通后 Guest 可使用厂商驱动的全部特性,如 GPU 编码器、网卡卸载、NVMe 多队列。
- 降低 CPU 开销:I/O 不再由宿主 CPU 代劳,vCPU 可以专注于业务负载,提升整机密度。
五、典型场景与配置片段
以 KVM/QEMU 为例,直通一块网卡通常需要先确认 IOMMU 分组,再把设备绑定到 vfio-pci,最后在 QEMU 命令行中通过 -device vfio-pci 分配。下面是一段常见的检查与绑定命令:
# 确认 IOMMU 已开启
dmesg | grep -e DMAR -e IOMMU
# 查看设备与 IOMMU 分组
lspci -nn | grep -i ethernet
for d in /sys/kernel/iommu_groups/*/devices/*; do
echo "IOMMU Group $(basename $(dirname $(dirname $d))): $(lspci -nns ${d##*/})"
done
# 绑定到 vfio-pci
echo 0000:01:00.0 > /sys/bus/pci/devices/0000:01:00.0/driver/unbind
echo vfio-pci > /sys/bus/pci/devices/0000:01:00.0/driver_override
echo 0000:01:00.0 > /sys/bus/pci/drivers/vfio-pci/bind
在 QEMU 中分配该设备:
qemu-system-x86_64 \
-enable-kvm \
-m 8G \
-cpu host \
-device vfio-pci,host=01:00.0,id=net0 \
-drive file=guest.qcow2,if=virtio
六、常见误区与复盘
误区一:只要开启 VT-d 就能直通。 实际上还需要内核支持、VFIO 绑定、IOMMU 分组合理,以及设备本身支持 FLR(Function Level Reset),否则 Guest 重启后设备可能无法恢复。
误区二:直通一定比 virtio 快。 对于小包、低频 I/O,virtio 的批量通知机制可能更省 CPU;直通的优势在高吞吐、低延迟、功能完整场景。选型应基于实测。
误区三:忽略 IOMMU 分组。 如果目标设备与宿主关键设备(如 SATA 控制器、USB 控制器)在同一分组,强行直通会连带把宿主设备也交给 Guest,导致宿主失去磁盘或键鼠。此时需要 ACS 覆盖或更换插槽。