VirtIO 半虚拟化设备:QEMU 性能飞跃的关键
为什么需要 VirtIO
传统设备模拟下,Guest 操作系统通过 I/O 端口和 MMIO 寄存器与 QEMU 模拟的硬件通信。每次 Guest 写一个寄存器,都要触发 VMEXIT → QEMU 模拟 → VMEXIT 返回。这个过程开销巨大——一个磁盘 I/O 可能涉及上百次 VMEXIT。
VirtIO 的核心思路:让 Guest 知道自己跑在 QEMU 里,用一套高效的共享内存队列直接通信。跳过寄存器模拟,跳过反复 VMEXIT。
VirtIO 架构
VirtIO 设备由三部分组成:
┌──────────────┐ 共享内存队列 ┌──────────────┐
│ Guest OS │ ←───────────────→ │ QEMU 设备 │
│ │ │ │
│ virtio 驱动 │ 通知机制 │ virtio 后端 │
│ │ ←──────────────→ │ │
└──────────────┘ └──────────────┘
- Guest virtio 驱动:Linux 内核原生支持(
CONFIG_VIRTIO_BLK、CONFIG_VIRTIO_NET等) - 共享内存队列(vring):Guest 和 Host 共同读写
- 通知机制:Guest 加中断到 Host,Host 加中断到 Guest(virtqueue 的 kick 和中断)
常用 VirtIO 设备
| 设备 | 用途 | QEMU 参数 |
|---|---|---|
| virtio-blk-pci | 磁盘 I/O | -drive file=xxx.qcow2,if=virtio |
| virtio-scsi-pci | 高级磁盘(热插拔更好) | -device virtio-scsi-pci |
| virtio-net-pci | 网络接口 | -device virtio-net-pci,netdev=n0 |
| virtio-gpu-pci | 3D 加速显卡 | -device virtio-gpu-pci |
| virtio-tablet-pci | 高分辨率鼠标 | -device virtio-tablet-pci |
| virtio-input-host-pci | Host 输入设备直通 | -device virtio-input-host-pci |
| virtio-iommu-pci | IOMMU 设备 | -device virtio-iommu-pci |
| virtio-rng-pci | 熵源(随机数) | -device virtio-rng-pci |
| virtio-balloon-pci | 气球驱动(内存动态调整) | -device virtio-balloon-pci |
启用 VirtIO 的命令行示例
qemu-system-x86_64 \
-accel kvm \
-cpu host -smp 4 -m 8G \
-drive file=disk.qcow2,if=virtio,format=qcow2 \
-device virtio-scsi-pci \
-device virtio-net-pci,netdev=n0 \
-netdev user,id=n0,hostfwd=tcp::2222-:22 \
-device virtio-gpu-pci \
-device virtio-tablet-pci \
-device virtio-rng-pci \
-nographic
这个配置把磁盘、网卡、显卡、鼠标、熵源全换成了 VirtIO 设备。Guest Linux 内核启动时自动加载 virtio 驱动,无需额外操作。
Guest 侧验证
在 Linux Guest 里查看 virtio 设备:
lspci | grep -i virtio
# 00:03.0 Ethernet controller: Red Hat, Inc. Virtio network device
# 00:04.0 SCSI storage controller: Red Hat, Inc. Virtio SCSI
# 00:05.0 Display controller: Red Hat, Inc. Virtio GPU
# ...
ls /sys/bus/virtio/devices/
# virtio0 virtio1 virtio2 virtio3 virtio4 virtio5
确认内核配置:
grep VIRTIO /boot/config-$(uname -r)
# CONFIG_VIRTIO=m
# CONFIG_VIRTIO_BLK=m
# CONFIG_VIRTIO_NET=m
# ...
如果这些驱动没编进内核或没作为模块加载,VirtIO 设备在 Guest 里会不可用。
Windows Guest 的 VirtIO
Windows 内核不自带 VirtIO 驱动,需要手动安装。步骤:
- 访问
github.com/virtio-win/kvm-guest-drivers-windows下载 ISO - 在 QEMU 里挂载这个 ISO:
-cdrom virtio-win.iso - 设备管理器里手动指定驱动位置
- 安装完成后 VirtIO 设备立即生效
virtio-win 项目由 Red Hat 维护,版本跟随 QEMU 主版本。
VirtIO vs 传统设备性能对比
磁盘 I/O 场景(fio 测试):
| 设备类型 | 4K 随机写 IOPS | 延迟 |
|---|---|---|
| IDE(模拟) | ~300 | ~3ms |
| AHCI(模拟) | ~5,000 | ~0.2ms |
| virtio-blk | ~50,000 | ~0.02ms |
| 物理 NVMe | ~100,000+ | ~0.01ms |
virtio-blk 比传统设备快一个数量级,接近物理硬件。网卡同理:virtio-net-pci 的吞吐量是 rtl8139 的 5 倍以上。
下一步
VirtIO 的高效依赖磁盘镜像格式。继续看 qcow2 格式详解。