2. 虚拟化基础
在进入KVM虚拟CPU与中断虚拟化的细节之前,必须先建立一张“全局地图”:虚拟化到底虚拟了什么?谁在负责虚拟化?KVM与QEMU各自扮演什么角色?只有把这些问题厘清,后续讨论vCPU调度、VMCS/VMCB、中断注入路径时,才不会迷失在零散的寄存器与代码路径中。
2.1 虚拟化的核心概念
虚拟化本质上是用软件抽象硬件资源,让多个相互隔离的执行环境共享同一套物理硬件。它围绕三个核心对象展开:
- CPU虚拟化:让Guest操作系统以为自己独占CPU,实际由Hypervisor调度物理CPU时间片。
- 内存虚拟化:Guest看到的“物理地址”是虚拟的,需要经过GPA→HPA的二次转换。
- I/O虚拟化:Guest访问的设备可能是模拟设备、半虚拟化设备或直通设备。
其中CPU虚拟化是中断虚拟化的基础。Guest执行特权指令时会被陷入(trap)到Hypervisor,由Hypervisor模拟执行或直接交给硬件处理。这种“陷入—模拟—返回”的循环,构成了虚拟化运行的基本节拍。
2.2 Hypervisor分类:Type 1 与 Type 2
Hypervisor(虚拟机监控器)按部署位置可分为两类:
| 类型 | 运行位置 | 典型代表 | 特点 |
|---|---|---|---|
| Type 1(裸金属) | 直接运行在硬件之上 | Xen、VMware ESXi、KVM(内核态) | 性能高、延迟低,适合数据中心 |
| Type 2(宿主型) | 运行在宿主OS之上 | VirtualBox、VMware Workstation、QEMU | 部署方便,性能与隔离性较弱 |
KVM的特殊之处在于:它把Linux内核本身变成了Type 1 Hypervisor。KVM以内核模块形式加载,借助Linux的调度、内存管理和驱动框架,既获得了裸金属级的硬件控制能力,又保留了Linux生态的丰富性。
2.3 KVM架构:内核态与用户态的协作
KVM不是完整的Hypervisor,而是Linux内核中的一个模块,提供CPU与内存虚拟化的核心能力。它的架构可以概括为“一个字符设备 + 两类执行模式”:
- /dev/kvm:用户态通过ioctl与KVM交互,创建VM、创建vCPU、设置寄存器、注入中断。
- VMX根模式:Host内核运行在根模式,拥有硬件完全控制权。
- VMX非根模式:Guest代码运行在非根模式,敏感操作触发VM-Exit回到KVM。
KVM只负责“让Guest跑起来”和“在必要时接管”。设备模拟、磁盘镜像、网络后端等大量工作,交给用户态的QEMU完成。
2.4 QEMU与KVM的协作关系
QEMU是一个功能完整的模拟器,可以纯软件模拟x86、ARM等架构;当它与KVM结合时,QEMU退化为“设备模型 + 控制平面”,CPU执行则交给KVM硬件加速。二者的协作关系如下:
QEMU进程
├─ 创建VM: ioctl(KVM_CREATE_VM)
├─ 创建vCPU线程: ioctl(KVM_CREATE_VCPU)
├─ 配置寄存器: KVM_SET_REGS / KVM_SET_SREGS
├─ 运行Guest: ioctl(KVM_RUN) ← 阻塞在KVM中
│ └─ VM-Exit原因返回:
│ ├─ EPT_VIOLATION → QEMU处理内存
│ ├─ IO_INSTRUCTION → QEMU模拟设备
│ └─ EXTERNAL_INTERRUPT → KVM/QEMU注入中断
└─ 设备模拟: 磁盘、网卡、串口、中断控制器
简单说:KVM管CPU和内存,QEMU管设备和外设。每次VM-Exit,控制权从KVM回到QEMU;QEMU处理完后再调用KVM_RUN,让Guest继续执行。中断虚拟化正是这条路径上最频繁、最敏感的一环。
2.5 典型应用场景
理解架构之后,再看它被用在哪些地方,能帮助建立“为什么这样设计”的直觉:
- 云计算多租户:一台物理机运行数十台虚拟机,KVM负责CPU/内存隔离,QEMU负责每台VM的设备。
- 开发测试环境:快速创建不同内核版本的Guest,验证驱动与中断行为。
- 嵌入式与实时场景:通过CPU亲和性、vCPU pinning、中断直通降低延迟。
- 安全隔离:利用虚拟化边界隔离不可信负载,配合KVM的嵌套虚拟化做沙箱。
2.6 常见误区与复盘
误区二:认为QEMU只是“模拟器”。在KVM模式下,QEMU的CPU执行路径被KVM接管,它主要承担设备模拟与控制平面。
误区三:忽略VM-Exit开销。频繁的VM-Exit(如每次I/O、每次中断)会显著影响性能,这也是后续中断虚拟化优化的核心动机。