3. 主流Hypervisor概览

KVM 这东西,说白了就是 Linux 内核里的一个“虚拟化开关”。我刚开始接触那会儿,总觉得它很神秘,后来拆开一看,其实没那么复杂。今天咱们就把 KVM 的里里外外捋一遍。

3.1 KVM 内核模块:虚拟化的“发动机”

KVM 本身不是一个完整的 Hypervisor,它只是 Linux 内核的一个模块。它的核心工作就三件:CPU 虚拟化、内存虚拟化、中断虚拟化。

我习惯把 KVM 模块比作“硬件加速器”。没有它,QEMU 纯软件模拟虚拟机,慢得让人抓狂。有了它,虚拟机可以直接在物理 CPU 上跑,性能接近原生。

KVM 模块加载命令:

# 检查 CPU 是否支持硬件虚拟化
egrep -c '(vmx|svm)' /proc/cpuinfo

# 加载 KVM 模块
modprobe kvm
modprobe kvm_intel   # Intel 处理器
# modprobe kvm_amd   # AMD 处理器

# 验证模块是否加载
lsmod | grep kvm

加载成功后,/dev/kvm 这个字符设备就会出现。它就是用户态和内核态通信的“门”。

KVM 模块 职责 关键接口
kvm.ko 核心框架,管理 VM 生命周期 ioctl 调用、内存映射
kvm_intel.ko Intel VT-x 硬件加速 VMX 根/非根模式切换
kvm_amd.ko AMD SVM 硬件加速 VMRUN/VMLOAD 指令

我的经验: 曾经在一台老服务器上死活加载不了 kvm_intel,折腾半天发现 BIOS 里 VT-x 没开。嗯,这坑我踩过,你们别重蹈覆辙。

3.2 QEMU 用户态组件:虚拟设备的“模拟器”

KVM 只管 CPU 和内存,那硬盘、网卡、显卡谁来管?答案是 QEMU。QEMU 跑在用户态,负责模拟各种 I/O 设备。

你想想看,虚拟机里要读写硬盘,数据怎么走?流程是这样的:

  1. 虚拟机里的驱动发起 I/O 请求
  2. KVM 捕获这个请求,退出到 QEMU
  3. QEMU 模拟设备行为,操作宿主机上的真实文件或设备
  4. 结果返回给虚拟机

这个过程叫“陷阱-模拟”。每次 I/O 都要上下文切换,性能损耗不小。所以后来才有了 virtio。

QEMU 启动虚拟机示例:

qemu-system-x86_64 \
  -enable-kvm \
  -m 4G \
  -smp 4 \
  -drive file=/var/lib/libvirt/images/ubuntu.qcow2,if=virtio \
  -netdev user,id=net0 \
  -device virtio-net,netdev=net0

注意 -enable-kvm 这个参数,它告诉 QEMU:“别自己模拟 CPU 了,用 KVM 的硬件加速!”

3.3 KVM 与 QEMU 协作流程:一张图说清楚

下面这张 SVG 图,我画的是 KVM 和 QEMU 怎么配合工作的。你看一眼就明白了。

KVM 与 QEMU 协作流程 用户态:QEMU 模拟 I/O 设备 管理虚拟机配置 处理 virtio 队列 通过 /dev/kvm 下发 ioctl 内核态:KVM 模块 CPU 虚拟化(VMX/SVM) 内存虚拟化(EPT/NPT) 中断虚拟化(APICv) 处理 VM-Exit 事件 物理硬件层 CPU(VT-x/SVM) | 内存(EPT/NPT) | I/O 设备 虚拟机(Guest OS) 运行在 VMX 非根模式下 ioctl VM Entry/Exit 直接执行 关键点: I/O 密集型操作 会触发 VM-Exit

流程其实很简单:

  • QEMU 通过 /dev/kvm 发 ioctl 告诉 KVM:“我要创建一个虚拟机”
  • KVM 在内核态分配 VMCS(虚拟机控制结构),配置 CPU 进入 VMX 非根模式
  • 虚拟机 直接在物理 CPU 上跑,直到遇到敏感指令或中断,触发 VM-Exit
  • KVM 处理 VM-Exit,如果是 I/O 请求,就交给 QEMU 模拟

注意: VM-Exit 是性能杀手。每次退出都要保存上下文、切换到根模式、再切回来。我曾经优化过一个数据库虚拟机,发现 VM-Exit 频率高达每秒 10 万次,后来通过调整中断合并和 virtio 参数,降到了 2 万次,性能提升明显。

3.4 virtio 半虚拟化驱动:告别“慢速模拟”

前面说了,纯模拟 I/O 设备性能差。virtio 就是来解决这个问题的。

virtio 的思路很简单:让虚拟机知道自己是个虚拟机。Guest 里装一个特殊的 virtio 驱动,它不模拟真实硬件,而是直接和 QEMU 通过共享内存通信。

对比项 全虚拟化(模拟) 半虚拟化(virtio)
驱动类型 模拟真实硬件(如 e1000 网卡) 专用 virtio 驱动
通信方式 陷阱-模拟,每次 I/O 都 VM-Exit 共享内存环形队列,减少 VM-Exit
性能 较差,CPU 开销大 接近原生,吞吐量高
兼容性 无需额外驱动,开箱即用 需要 Guest 安装 virtio 驱动

我个人的习惯是:所有生产环境的虚拟机,一律用 virtio。除非遇到特别老的系统(比如 Windows 2003),才考虑用模拟设备。

virtio 设备类型:

  • virtio-blk:块设备(硬盘)
  • virtio-net:网络设备
  • virtio-scsi:SCSI 控制器
  • virtio-balloon:内存气球(动态内存调整)
  • virtio-console:控制台

virtio 的核心是 vring(虚拟环形队列)。Guest 和 Host 共享一段内存,Guest 把 I/O 请求放到队列里,QEMU 从队列里取出来处理,处理完再放回去。整个过程不需要频繁的 VM-Exit,效率高得多。

避坑指南: 我曾经在 CentOS 6 上装 virtio 驱动,结果系统启动时直接 kernel panic。后来发现是内核版本太老,不支持 virtio 1.0 规范。解决办法:要么升级内核,要么在 QEMU 命令行里指定 disable-modern=true 回退到 virtio 0.9。

总结一下这一节的核心:

  • KVM 是内核模块,提供 CPU/内存/中断的硬件加速
  • QEMU 是用户态进程,负责设备模拟和虚拟机管理
  • 两者通过 /dev/kvm 和 ioctl 通信
  • virtio 是半虚拟化驱动,大幅提升 I/O 性能