在 Windows 11 上打开系统信息(msinfo32),「基于虚拟化的安全性」栏里经常会看到「正在运行」——即使是从未创建过虚拟机的机器。
这意味着下面这一事实。在那台 PC 上,主机 Windows 自身已经运行在虚拟机监控程序之上。「虚拟化」不再只是在 Hyper-V 管理器里创建虚拟机的人的技术。在 Windows 11 上,基于虚拟化的安全性(VBS)在满足条件的配置上默认启用——例如在兼容硬件上全新安装1——而 WSL2 和 Windows Sandbox 都建立在同一套 Windows 虚拟机监控程序之上。你每天使用的 Windows 下面,已经多了一层软件。
本系列「Windows 虚拟化的深层」从基础开始,追那一层里发生了什么。
「Windows 虚拟化的深层」全 3 回
- 第1回(本文):虚拟机监控程序与分区
追启用 Hyper-V 后,主机 Windows 最终在哪里运行。 - 第2回:连内核也看不见的内存 ── VBS、HVCI 与 Credential Guard
追 Windows 把管理员和内核都读不到的秘密放在哪里。 - 第3回:数秒启动的虚拟机 ── WSL2、Windows Sandbox 与容器
从内存和映像如何共享,追完整虚拟机虽重、WSL2 和 Sandbox 却轻的原因。
第1回要回答的问题只有一个。
启用 Hyper-V 后,主机 Windows 最终在哪里运行?
目标读者是使用 Hyper-V、WSL2 或 Windows Sandbox、希望从机制上理解下面在跑什么的开发者和运维人员。前提环境是 x64 Windows 10/11 或现行 Windows Server(本文关于环、VT-x/AMD-V、EPT/RVI 的讨论以 x64 为前提;Arm64 使用异常级别等不同机制)。所需背景大约是内核模式与用户模式的区分;不需要虚拟机操作经验或虚拟机监控程序开发知识。难度为中级。我们覆盖 CPU 虚拟化扩展的概念,但不进入指令集细节。
1. 先说结论
听到 Hyper-V,人们可能想象「坐在 Windows 上面的、用来跑虚拟机的软件」。实际结构正好相反。
从启用 Hyper-V 并重启的那一刻起,控制物理 CPU 和内存的是虚拟机监控程序,主机 Windows 作为第一个、有特权的分区——「根分区」——运行在它上面。
虚拟机监控程序是夹在硬件和操作系统之间的薄软件层,创建称为「分区」的隔离执行环境,并调解对硬件的访问。2 主机 Windows 进入的是根分区;虚拟机进入的是子分区。根分区被特殊对待(它能直接访问物理设备并持有管理栈),但就它不直接控制物理 CPU 这一点而言,它和子分区站在同一位置。
flowchart TB
accTitle: 启用 Hyper-V 后的整体结构
accDescr: 虚拟机监控程序直接坐在物理硬件上,其上是持有主机 Windows 的根分区和持有虚拟机的子分区
hw["物理硬件"] --> hv["虚拟机监控程序"]
hv --> root["根分区(主机 Windows)"]
hv --> child1["子分区(虚拟机)"]
root -.-> stack["持有虚拟化管理栈和设备驱动程序"]
图 1: Hyper-V 不是「Windows 上面的虚拟机软件」,而是钻到 Windows 下面的一层,主机操作系统自身运行在根分区里。
你也许会想:「启用之后感觉没什么不同,真的发生了这么大的颠倒吗?」发生了。正因为如此,这一结构通常不被注意到。本文沿 CPU、内存、设备 I/O 三条轴拆开这一张图。
2. 从 CPU 看 ── 环下面还有一层特权
2.1. 环保护复习
x64 CPU 有特权级别(环),Windows 把内核模式跑在环 0,用户模式跑在环 3。应用程序不能直接碰硬件,因为特权指令不能从环 3 执行。
那么,如何在同一颗物理 CPU 上安全地安置多个都在环 0 运行的操作系统内核?每个内核都按「我控制 CPU」来写。把环 0 给它们全部会冲突;不给它们就跑不起来。
flowchart TB
accTitle: 多个操作系统内核都要环 0 的问题
accDescr: 主机和客户机内核都按环 0 的全部权限来写,因此仅靠传统的环阶梯无法把它们安全安置在同一颗物理 CPU 上
k1["主机内核(假定环 0)"] --> want["要求控制物理 CPU"]
k2["客户机内核(假定环 0)"] --> want
want --> conflict["传统的环无法调和"]
conflict --> need["需要环 0 之上的调解者"]
图 2: 环阶梯是按单个操作系统来建的,安置多个内核需要再高一层特权。
2.2. 虚拟化扩展 ── 留给虚拟机监控程序的模式
解决这个问题的,是 CPU 的虚拟化扩展(Intel VT-x/AMD-V)。Hyper-V 需要具备这一功能的处理器。2 虚拟化扩展在与传统环分开的轴上,增加了「虚拟机监控程序的执行模式」和「客户机的执行模式」。这是比环 0 更强的特权,有时被戏称为「环 -1」。
- 客户机内核继续像以前一样在环 0 运行。不需要改写。
- 不过那个环 0 是「客户机模式里的环 0」,它并不控制整颗物理 CPU。
- 当客户机碰到需要虚拟机监控程序介入的特定操作(被配置为拦截的指令,或异常、违规)时,CPU 自动把控制权交给虚拟机监控程序(VM Exit)。虚拟机监控程序处理完后返回客户机(VM Entry)。普通内存访问只要 SLAT 转换成功,就不会发生 VM Exit。
中断也一样。分区不直接碰物理处理器;虚拟机监控程序接收中断并把它们导向各分区。2
flowchart TB
accTitle: 客户机执行与 VM Exit 的流程
accDescr: 客户机内核和应用在客户机模式的环 0 与环 3 运行;普通内存访问经 SLAT 转换通过,而被配置的拦截和异常会引发把控制权交给虚拟机监控程序的 VM Exit,再经 VM Entry 返回客户机
guest["在客户机模式运行(含环 0 内核)"] --> op{"需要介入的操作?(已配置的拦截/异常)"}
op -->|否| cont["照原样继续执行"]
op -->|是| exitEv["VM Exit(CPU 交出控制权)"]
exitEv --> hvp["虚拟机监控程序处理"]
hvp --> entry["经 VM Entry 返回客户机"]
entry --> guest
图 3: 客户机操作系统无需改写,继续在环 0 运行,CPU 只在需要时才呼叫虚拟机监控程序。
这一来回很像内存系列里追过的流程——「页错误进入内核,再回到同一条指令」。CPU 通过异常或转换机制截获控制权,让更高层的管理者决定,然后返回。在 Windows 的深层,这种形状一次次出现。
2.3. Type 1 与 Type 2 ── 差别在坐在哪里
虚拟机监控程序大致分为直接跑在硬件上的 Type 1(裸机),以及跑在主机操作系统之上的 Type 2(托管)。Hyper-V 是 Type 1。3 VirtualBox 和 VMware Workstation(独立运行时)被归为 Type 2。
听到 Type 1,人们容易想象「没有主机操作系统的纯服务器配置」,但 Hyper-V 不同。主机 Windows 并没有消失——它「搬家」进了根分区。启用 Hyper-V 并重启后,启动过程中虚拟机监控程序先启动,主机 Windows 再作为根分区在它上面起来。
flowchart TB
accTitle: Type 1 与 Type 2 虚拟机监控程序的差异
accDescr: Type 2 中主机操作系统坐在硬件上,虚拟机监控程序和虚拟机坐在主机操作系统上;Type 1 的 Hyper-V 中虚拟机监控程序直接坐在硬件上,主机操作系统自身进入其上的根分区
subgraph t2 ["Type 2(托管)"]
hw2["硬件"] --> hostos["主机操作系统"]
hostos --> hv2["虚拟机监控程序"]
hv2 --> vm2["虚拟机"]
end
subgraph t1 ["Type 1(Hyper-V)"]
hw1["硬件"] --> hv1["虚拟机监控程序"]
hv1 --> root1["根分区(主机操作系统)"]
hv1 --> vm1["虚拟机"]
end
vm2 ~~~ hw1
图 4: Type 2 中虚拟机监控程序坐在主机操作系统上,而 Type 1 的 Hyper-V 顺序颠倒,主机操作系统自身坐在再下一层之上。
从启动时间线看,启用时发生的变化是这样的。
flowchart TB
accTitle: 启用 Hyper-V 后的启动顺序
accDescr: 加电后,启动过程中虚拟机监控程序先启动,主机 Windows 再作为根分区在它上面起来,虚拟机、VBS 等在那之后启动
poweron["加电并开始启动"] --> bhv["虚拟机监控程序先启动"]
bhv --> broot["主机 Windows 作为根分区启动"]
broot --> blater["虚拟机、VBS、WSL2 等在其上启动"]
broot -.-> feel["用户体验不变"]
图 5: 顺序的颠倒在登录画面出现之前就已经完成,主机操作系统从一开始就在虚拟机监控程序上起来。
3. 分区 ── 隔离的单位
3.1. 只有根分区才有的角色
分区是虚拟机监控程序提供的逻辑隔离单位。2 不过并非每个分区都平等。有些东西只有根分区才有。
- 对物理设备的直接访问。磁盘、网卡、GPU 等的设备驱动程序住在根分区里的 Windows 中,而不是虚拟机监控程序里。Windows Server 上的 Hyper-V 有一种把特定 PCIe 设备直接分配给子分区的配置(Discrete Device Assignment);那种情况下根会放开该设备(客户端 Windows 没有这一功能)。4
- 虚拟化管理栈。掌管创建、启动、停止虚拟机的 VMMS(Virtual Machine Management Service),以及每台虚拟机的工作进程(vmwp.exe),运行在根分区的用户模式。5 这些是 Hyper-V 的虚拟机管理功能的一部分,因此在仅为 VBS 或 WSL2 运行虚拟机监控程序的主机上可能不存在。
- 创建子分区的权利。根分区通过 hypercall API(进入虚拟机监控程序的调用接口)创建子分区。2
这一设计有原因。若把每个设备驱动程序都放进虚拟机监控程序本身,虚拟机监控程序会变得巨大,缺陷和攻击入口会增多。虚拟机监控程序把自己限制在调解 CPU 和内存的最小工作上,把设备的照料留给根分区里的 Windows。这一角色划分让 Hyper-V 保持纤薄。
flowchart TB
accTitle: 根分区与子分区的角色划分
accDescr: 根分区持有虚拟化管理栈和物理设备驱动程序,并经 hypercall 创建子分区;子分区通常只看见虚拟设备,在 Windows Server 的 Discrete Device Assignment 下则直接访问被分配的设备
subgraph rootp ["根分区"]
vmms["VMMS 与工作进程"]
drv["物理设备驱动程序"]
end
subgraph childp ["子分区"]
gos["客户机操作系统"]
vdev["通常配置下只看见虚拟设备"]
end
vmms -->|经 hypercall 创建与管理| childp
hv2["虚拟机监控程序(只调解 CPU 与内存)"] --- rootp
hv2 --- childp
图 6: 把设备驱动程序和管理栈放在根分区一侧,正是让虚拟机监控程序本身保持纤薄的原因。
3.2. 从子分区看见的世界
子分区里的客户机操作系统在通常的虚拟设备配置下不能直接看见物理硬件(唯一例外是上一节所述、Windows Server 上经 Discrete Device Assignment 分配的设备)。它能看见的是虚拟处理器、看起来属于自己的内存空间,以及虚拟设备。对虚拟设备的请求经 VMBus 或虚拟机监控程序转发到根分区。2 另一方面,CPU 时间分配和经 SLAT 的内存转换由虚拟机监控程序直接处理,不经过根。根调解的是设备 I/O,不是每一种物理资源。
flowchart TB
accTitle: 从子分区看见的世界
accDescr: 客户机操作系统看见的是虚拟处理器、分区私有的内存空间和虚拟设备;对虚拟设备的请求经 VMBus 等转发到根分区,CPU 时间和内存转换由虚拟机监控程序直接处理,Windows Server 的 Discrete Device Assignment 配置下只有被分配的设备被直接访问
gos2["客户机操作系统(子分区)"] --> vcpu["虚拟处理器"]
gos2 --> rest{"内存还是设备?"}
rest --> gpa2["私有内存空间"]
rest --> vdev2["虚拟设备"]
vdev2 --> rootx["转发到根"]
rootx -.-> vbus["经 VMBus 等"]
gos2 -.-> phys2["物理 CPU、RAM、设备"]
phys2 -.-> hid["不能直接看见"]
phys2 -.-> dda2["DDA:被分配的设备"]
dda2 -.-> ddaN["Windows Server"]
vcpu ~~~ phys2
图 7: 在通常的虚拟设备配置下,客户机看见的一切都是虚拟窗口,通向物理的路径经过调解者;只有 Windows Server 上经 DDA 分配的设备是例外。
这里重要的是,对运行在主机 Windows 上的应用,这一结构几乎是透明的。Win32 API 调用和页错误处理仍像以前一样,由根分区里的 Windows 内核处理。只有碰到被配置的拦截或异常时,虚拟机监控程序才介入。
4. 从内存看 ── 地址转换多了一级
4.1. 三种地址
在内存系列第1回,我们追过虚拟地址经页表转换成物理地址的流程(「虚拟地址变成物理 RAM 的瞬间」)。在虚拟化环境中,那一转换下面又多了一级,于是有三种地址。
| 地址 | 缩写 | 谁管理 |
|---|---|---|
| 客户机虚拟地址 | GVA | 客户机操作系统页表 |
| 客户机物理地址 | GPA | 客户机操作系统以为是「物理」的地址 |
| 系统物理地址 | SPA | 虚拟机监控程序(RAM 中的实际位置) |
客户机操作系统用自己的页表把 GVA 转成 GPA。不过客户机看见的 GPA 不是真正的物理地址;它是每个分区专用的私有内存空间。2 把 GPA 映射到 RAM 中的实际位置(SPA)是虚拟机监控程序的工作。
4.2. SLAT ── 硬件里的两级转换
若只用软件做这第二级转换,虚拟机监控程序就必须逐条跟踪每一次客户机页表更新,从性能上看不现实。于是 CPU 提供了在硬件中遍历第二级转换表的机制。那就是 SLAT(Second Level Address Translation);Intel EPT(Extended Page Tables)和 AMD RVI 是其实现。现行 Hyper-V 需要支持 SLAT 的 64 位处理器。4
flowchart TB
accTitle: 经 SLAT 的两级地址转换
accDescr: 客户机虚拟地址由客户机操作系统页表转换成客户机物理地址,再由虚拟机监控程序管理的 SLAT 进一步转换成系统物理地址,到达实际 RAM
gva["客户机虚拟地址(GVA)"] -->|客户机操作系统页表| gpa["客户机物理地址(GPA)"]
gpa -->|"SLAT(EPT/RVI 转换表)"| spa["系统物理地址(SPA)"]
spa --> ram["物理 RAM"]
gpa -.-> note["客户机只是以为它是物理的一层"]
图 8: 客户机页表下面还有一张由虚拟机监控程序管理的转换表,CPU 在硬件中遍历两者。
SLAT 不是只为虚拟机执行效率而存在的功能。第2回将看到的 VBS,把「可以按特权级别拥有不同的 SLAT 转换表」这一性质当作安全边界的材料。之所以能创建连内核也看不见的内存,是因为虚拟机监控程序握着这第二级转换。这会成为整个系列的伏线,所以先记住一点:「转换表的所有者是虚拟机监控程序」。
5. 从设备 I/O 看 ── VMBus 与两类设备
5.1. 模拟设备的极限
向子分区展示设备的经典做法,是用软件完整模仿真实硬件(例如旧的 IDE 控制器)。兼容性高,因为客户机操作系统的收件箱驱动程序可以原样工作,但客户机每次碰到 I/O 端口都会发生 VM Exit,性能无法扩展。
flowchart TB
accTitle: 对模拟设备的 I/O 为何慢
accDescr: 客户机每次操作 I/O 端口,控制权都经 VM Exit 转到虚拟机监控程序一侧,设备在软件中被模仿,再返回客户机,因此来回重复且慢
gio["客户机操作 I/O 端口"] --> vex["发生 VM Exit"]
vex --> emu2["在软件中模拟设备"]
emu2 --> back["经 VM Entry 返回客户机"]
back -->|下一次端口操作再重复| gio
图 9: 这一来回会在一次磁盘访问背后跑许多次,兼容性的代价用性能来付。
5.2. VMBus 与 VSP/VSC ── 为虚拟化设计的快速路径
于是 Hyper-V 有一套按虚拟化为前提设计的「合成设备」机制。角色有三个。2
- VMBus:分区间的逻辑通信通道。它提供使用共享内存的高速分区间通信。3
- VSP(Virtualization Service Provider):驻在根分区一侧的服务,接收来自子分区的设备请求,并把它们桥接到根一侧的设备/后端栈。请求可能到达物理设备,也可能由虚拟磁盘或虚拟交换机等主机侧后端处理。
- VSC(Virtualization Service Consumer):进入子分区一侧客户机操作系统的合成设备驱动程序。它经 VMBus 向 VSP 发送请求。
以客户机操作系统的存储请求为例,流程是这样的。客户机应用的 WriteFile 沿客户机内核的 I/O 栈下降,在底部到达 VSC(而不是真实硬件)。VSC 把请求放到 VMBus 上交给根分区的 VSP,VSP 再把请求流入根一侧的 I/O 栈。在虚拟磁盘(VHDX)配置中,这次写入被当作对主机上 VHDX 文件的写入处理,最终到达物理磁盘。这种方法称为 Enlightened I/O(意识到虚拟化的 I/O),通过绕过设备模拟层来提高效率。2
flowchart TB
accTitle: 合成设备的 I/O 路径
accDescr: 来自子分区应用的 I/O 请求经客户机内核到达 VSC,经 VMBus 跨到根分区的 VSP,在 VSP 桥入的根一侧 I/O 栈上,可能经物理设备驱动程序到达真实设备,也可能由虚拟磁盘或虚拟交换机等主机侧后端处理
app["子分区中的应用"] --> gk["客户机内核 I/O 栈"]
gk --> vsc["VSC(合成设备驱动程序)"]
vsc -->|VMBus| vsp["VSP(根分区一侧)"]
vsp --> rio["根一侧 I/O 栈"]
rio --> pdrv["物理设备驱动程序"]
rio --> hb["主机侧后端(虚拟磁盘、虚拟交换机等)"]
pdrv --> dev["物理设备"]
图 10: 使用合成设备时,客户机 I/O 经 VMBus 跨到根分区,再经根一侧的栈到达真实设备或主机侧后端。
也就是说,虚拟机的磁盘 I/O 或网络是否快,不仅取决于客户机一侧,也取决于根分区一侧 I/O 栈和设备驱动程序的状态。调查虚拟机性能问题时主机侧观察必不可少,原因是路径实际上经过主机。
flowchart TB
accTitle: 模拟设备与合成设备
accDescr: 模拟设备模仿真实硬件,使收件箱客户机驱动程序能工作但较慢;合成设备是假定 VMBus 的专用驱动程序,较快
dev2{"展示给子分区的设备"} --> emu["模拟设备"]
dev2 --> syn["合成设备"]
emu -.-> emuP["模拟真实硬件;兼容性优先"]
emuP -.-> emuC["每次 I/O 都需介入;慢"]
syn -.-> synP["围绕 VMBus 设计;快"]
synP -.-> synC["客户机需要匹配的驱动程序"]
图 11: 两类虚拟设备中,模拟设备承担操作系统刚装好时的兼容性,合成设备承担日常使用中的性能。
6. 为何即便从不使用虚拟机,这也不是别人的事
至此的结构看起来像「给搭虚拟机的人讲的故事」。不过正如开篇所说,在现行 Windows 上,虚拟机监控程序是日常生活的一部分。
- 基于虚拟化的安全性(VBS)。它用 Windows 虚拟机监控程序创建隔离环境,并把安全功能安置在那里。在 Windows 11 上,当满足在兼容硬件上全新安装等条件时默认启用。1 细节见第2回。
- WSL2。它在轻量实用虚拟机里运行真正的 Linux 内核。6
- Windows Sandbox。由虚拟机监控程序隔离的一次性 Windows 环境。7 两者都在第3回讲述。
flowchart TB
accTitle: 坐在同一虚拟机监控程序上的日常功能
accDescr: 不仅是 Hyper-V 虚拟机,在全新安装等条件下默认启用的 VBS,以及 WSL2 和 Windows Sandbox,都建立在同一套 Windows 虚拟机监控程序之上
base["Windows 虚拟机监控程序"] --> f1["Hyper-V 虚拟机"]
base --> f2["VBS(全新安装等条件下默认启用)"]
base --> f3["WSL2"]
base --> f4["Windows Sandbox"]
f2 -.-> daily["为何从不使用虚拟机的 PC 上也在运行"]
图 12: 基础只有一个,这张图正是「虚拟化是给使用虚拟机的人讲的故事」这一假定崩塌的地方。
实务上人们还常踩的一点是与第三方虚拟化软件的共存。因为虚拟机监控程序独占使用 CPU 的虚拟化扩展,在 Windows 虚拟机监控程序正在运行的环境里,VirtualBox 等无法按传统方式(自己使用 CPU 虚拟化扩展的方式)运行。为此提供了称为 Windows Hypervisor Platform 的公开 API,第三方虚拟化栈可以坐在 Windows 虚拟机监控程序之上运行。8 现行 VirtualBox/VMware 凭借这一机制可以与 WSL2 共存,但切换模式带来的性能和功能差异,有时被观察到成「启用 Hyper-V(或 VBS)之后,虚拟化软件的行为变了」。
flowchart TB
accTitle: 谁拥有 CPU 虚拟化扩展,以及第三方虚拟化软件的路径
accDescr: Windows 虚拟机监控程序运行时独占 CPU 虚拟化扩展;支持 WHP 的第三方虚拟化软件经 Windows Hypervisor Platform 在其上运行,不支持 WHP 的实现无法运行或功能受限
vt["CPU 虚拟化扩展(VT-x/AMD-V)"] --> hvon{"Windows 虚拟机监控程序在运行吗?"}
hvon -->|否| direct["第三方软件可以直接使用"]
hvon -->|是| own["虚拟机监控程序独占使用"]
own --> whp["Windows Hypervisor Platform"]
whp --> third["支持 WHP 的第三方软件在其上运行"]
third -.-> nowhp["不支持的实现无法运行或受限"]
图 13: 虚拟化扩展只有一个所有者,虚拟机监控程序运行时能共存的第三方软件,只有支持公开 API(WHP)的软件。
7. 自己看一看
你可以在自己的机器上确认虚拟机监控程序是否在运行。
首先是不需要管理员权限就能跑的检查。
# Whether we are running on top of a hypervisor
(Get-CimInstance Win32_ComputerSystem).HypervisorPresent
# VBS status (same source as "Virtualization-based security" in msinfo32)
Get-CimInstance -Namespace root/Microsoft/Windows/DeviceGuard `
-ClassName Win32_DeviceGuard |
Select-Object VirtualizationBasedSecurityStatus
VirtualizationBasedSecurityStatus 用数字返回 VBS 运行状态(2 表示「正在运行」)。9
有一点要注意。HypervisorPresent 只告诉你「我们是否运行在虚拟机监控程序之上」;它不区分根与子。若在虚拟机里的 Windows 上运行,它仍返回 True,作为子分区。若在物理 PC 上的 Windows 上为 True,那台 Windows 在根分区里——要结合执行环境来读。
接下来是命令提示符里的经典。
systeminfo
看输出末尾的「Hyper-V Requirements」。在虚拟机监控程序尚未运行的机器上,会列出各项要求——SLAT 支持、虚拟化扩展是否启用等。在虚拟机监控程序已经运行的机器上,不再是要求列表,而是一行:「A hypervisor has been detected. Features required for Hyper-V will not be displayed。」4 因此那一行就是在说你的 Windows 运行在某个虚拟机监控程序之上。和 HypervisorPresent 一样,需要把它读成物理 PC 上「在根分区里」,或虚拟机里「作为子分区」。
即便 systeminfo 的每一项要求都是「Yes」,那也只表示硬件一侧已就绪。Hyper-V 功能本身在 Pro、Enterprise、Education 版本上可用,Home 上没有。10
在图形界面中,查看 msinfo32「系统摘要」下的「基于虚拟化的安全性」行。注意任务管理器 CPU 窗格里的「虚拟化: 已启用」只表示虚拟化扩展是否已在固件中启用,与虚拟机监控程序是否在运行是另一条信息。
flowchart TB
accTitle: 如何检查虚拟机监控程序是否在运行
accDescr: 若 systeminfo 显示已检测到虚拟机监控程序,则你运行在虚拟机监控程序上(物理 PC 上在根分区里);若出现 Hyper-V Requirements 列表则尚未运行,于是检查 SLAT、VM Monitor Mode Extensions、DEP 等每一项要求,但全部 Yes 只表示硬件一侧已就绪,Hyper-V 功能还有版本要求
start2["运行 systeminfo"] --> q1{"Requirements 栏?"}
q1 -->|Detected| running["虚拟机监控程序在运行"]
running -.-> runN["在根分区里"]
runN -.-> runN2["在物理 PC 上"]
q1 -->|Listed| notyet["尚未运行"]
notyet --> q2{"全部要求都是 Yes?"}
q2 -->|全部 Yes| can["硬件一侧已就绪"]
can -.-> ed["需要 Pro / Ent / Edu"]
q2 -->|有些 No| uefi["检查 UEFI/BIOS 项"]
图 14: systeminfo 的「Hyper-V Requirements」栏兼作运行状态检查和前提检查。
8. 实务中要避免的三种误读
8.1. 「我们没启用 Hyper-V,所以虚拟化和我们的 PC 无关」
即便没有启用 Hyper-V 功能(管理工具和虚拟机执行环境),只要 VBS 已启用,Windows 虚拟机监控程序就在运行。调查驱动程序兼容性问题、性能测试或第三方虚拟化软件故障时,检查的是 HypervisorPresent 和 VBS 运行状态——而不是功能是否启用。
8.2. 「任务管理器写着『虚拟化: 已启用』,所以 Hyper-V 在运行」
那一显示是关于固件设置(VT-x/AMD-V 是否可用)。从 systeminfo 的「A hypervisor has been detected」判断虚拟机监控程序的运行状态。反过来,若任务管理器写着「已禁用」,也无法启用 Hyper-V 或 WSL2,所以先检查 UEFI/BIOS 设置。
flowchart TB
accTitle: 容易混淆的三项检查
accDescr: 任务管理器的虚拟化栏显示固件设置,Windows 功能列表显示安装状态,systeminfo 或 HypervisorPresent 显示运行状态;各自回答不同的问题
q3{"哪个问题?"}
q3 --> fw{"固件还是 Windows?"}
q3 --> c3["虚拟机监控程序在运行吗?"]
fw --> a3["固件扩展?"]
fw --> b3["Hyper-V 功能开了吗?"]
a3 -.-> a3t["任务管理器 CPU 窗格"]
b3 -.-> b3t["Windows 功能界面"]
c3 -.-> c3t["systeminfo"]
c3 -.-> c3tp["HypervisorPresent"]
图 15: 这是三个独立的问题,从任一显示推断另外两个都是误读。
8.3. 「虚拟机慢就是客户机操作系统的问题」
合成设备 I/O 经 VMBus 跨到根分区的 VSP,并经过根一侧的设备/后端栈(物理驱动程序,加上虚拟交换机和虚拟磁盘处理)。若只看客户机内部的计数器,就找不到坐在主机侧存储或网卡上的瓶颈。虚拟机性能问题的原则是从两侧观察:客户机和主机(根分区)。
9. 小结
- 启用 Hyper-V 后,虚拟机监控程序直接跑在硬件上,主机 Windows 作为根分区运行。2
- 客户机操作系统内核继续在环 0 运行,只有被配置为拦截的操作以及异常经 VM Exit 交给虚拟机监控程序。普通内存访问经 SLAT 转换通过。
- 只有根分区持有物理设备驱动程序和虚拟化管理栈,并经 hypercall 创建子分区。2
- 内存变成 GVA→GPA→SPA 的两级转换,第二级由 SLAT(EPT/RVI)在硬件中处理。现行 Hyper-V 需要 SLAT。4
- 设备 I/O 以 VSC→VMBus→VSP 的合成设备路径为主,性能也取决于主机侧 I/O 栈。2
- 在 Windows 11 上,因为 VBS 在满足全新安装等条件的设备上默认启用,即便从不使用虚拟机的 PC 上虚拟机监控程序在运行也不少见。1 可以用
HypervisorPresent和 systeminfo 确认运行状态。
第1回的全貌浓缩成这一张图。
flowchart TB
accTitle: 第1回的全貌
accDescr: 虚拟机监控程序坐在根分区和子分区之下;CPU 通过调度虚拟处理器分配(仅在已配置的拦截和异常上发生 VM Exit),内存由两级 SLAT 转换调解,合成设备 I/O 经 VMBus 转发并由根分区的 VSP 处理,模拟设备和 Discrete Device Assignment 有其他路径
up["根分区 + 子分区"] --> hvS["虚拟机监控程序"]
hvS --> cpuS["CPU:调度虚拟处理器"]
hvS --> memS["内存:SLAT"]
cpuS -.-> cpuN["拦截时 VM Exit"]
memS -.-> memN["两级转换"]
memS ~~~ devS
devS["设备:VMBus I/O"] --> vspS["根一侧 VSP 处理"]
devS -.-> devN["模拟 / DDA:其他"]
图 16: CPU 调度和内存转换由虚拟机监控程序直接处理(仅在介入时 VM Exit),合成设备 I/O 由 VMBus 另一端的根分区(VSP)调解。
续篇见第2回「连内核也看不见的内存 ── VBS、HVCI 与 Credential Guard」。
我们接过本文的伏线——虚拟机监控程序握着 SLAT 转换表——追 Windows 如何创建「管理员和内核都读不到的内存」。
相关文章
- Windows 内存的深层(第1回) ── 虚拟地址变成物理 RAM 的瞬间:页错误的全过程
- Windows的「内存使用量」究竟表示什么 ── 正确解读 Working Set・Private Bytes・Commit・页面文件
- 用 Windows Sandbox 加快应用验证的方法
- 把 Windows 的「处理器计划」改成「后台服务」会发生什么 - 整理 quantum、优先级提升、P-Core/E-Core
相关咨询领域
小村软件有限公司承接 Windows 应用的验证环境设计、虚拟化环境中的性能调查,以及驱动程序和外围设备兼容性问题的分析。
参考链接
-
Microsoft Learn, Silicon assisted security. 关于 VBS 使用硬件虚拟化把安全内核与普通操作系统隔离,以及在 Windows 11 全新安装时,满足前提条件的设备上 VBS 和 HVCI 默认启用。 ↩ ↩2 ↩3
-
Microsoft Learn, Hyper-V Architecture. 关于虚拟机监控程序以分区作为隔离单位;根分区经 hypercall API 创建子分区;分区在私有虚拟内存空间中运行、不直接访问物理处理器;VMBus、VSP、VSC 与 Enlightened I/O 的角色;以及需要硬件虚拟化扩展(Intel VT/AMD-V)。 ↩ ↩2 ↩3 ↩4 ↩5 ↩6 ↩7 ↩8 ↩9 ↩10 ↩11 ↩12
-
Microsoft Learn, Hyper-V architecture (Performance Tuning). 关于 Hyper-V 是 Type 1 虚拟机监控程序、根分区拥有物理 I/O 设备,以及 VMBus 提供使用共享内存的高性能分区间通信。 ↩ ↩2
-
Microsoft Learn, System requirements for Hyper-V on Windows and Windows Server. 关于需要支持 SLAT 的 64 位处理器和 VM Monitor Mode Extensions;可以在 systeminfo 的「Hyper-V Requirements」栏确认要求是否满足;虚拟机监控程序运行时显示「A hypervisor has been detected」;以及 Discrete Device Assignment 可以把特定设备直接分配给子分区。 ↩ ↩2 ↩3 ↩4
-
Microsoft Learn, Appendix B: Hyper-V Architecture and Feature Overview. 关于 VMMS(Virtual Machine Management Service)管理子分区内虚拟机的状态,以及每台虚拟机在根分区的用户模式中启动一个工作进程(VMWP)。 ↩
-
Microsoft Learn, Comparing WSL Versions. 关于 WSL2 在轻量实用虚拟机里运行真正的 Linux 内核,以及与现行 VMware 和 VirtualBox 一起使用的注意事项。 ↩
-
Microsoft Learn, Windows Sandbox architecture. 关于 Windows Sandbox 是结合容器技术与虚拟机监控程序隔离的轻量 Windows 环境。 ↩
-
Microsoft Learn, Windows Hypervisor Platform. 关于提供用户模式 API,使第三方虚拟化栈可以在 Windows 虚拟机监控程序之上创建和管理分区。 ↩
-
Microsoft Learn, Enable Hotpatch for Azure Arc-enabled servers. 关于可以通过 Win32_DeviceGuard 类上的 VirtualizationBasedSecurityStatus 确认 VBS(虚拟安全模式)的运行状态。 ↩
-
Microsoft Learn, Install Hyper-V. 关于 Hyper-V 可在 Windows 10/11 的 Pro 或 Enterprise 等上启用,无法在 Home 版本上安装。 ↩
相关文章
共享相同标签的最新文章。可以围绕相近的主题进一步加深理解。
Windows 虚拟化的深层(第3回) ── 数秒启动的虚拟机:WSL2、Windows Sandbox 与容器为何这么轻
WSL2 和 Windows Sandbox 为何数秒启动、用起来这么轻?本文从动态基础映像、直接映射、动态内存分配讲到 Hyper-V 隔离容器,讲解其机制。
Windows 虚拟化的深层(第2回) ── 连内核也看不见的内存:VBS、HVCI 与 Credential Guard 的机制
在兼容硬件上全新安装时,VBS 默认启用,并用虚拟机监控程序与 SLAT 创建比内核更强的隔离。本文讲解 VTL、安全内核、HVCI 与 Credential Guard 的结构。
Win32 线程池 API ── 用 CreateThreadpoolWork 实现不自建线程的并发
原生代码里是否到处调用 CreateThread?本文根据一手资料讲解 Vista 重新设计的 Win32 线程池 API——work、timer、wait、io 四种对象、清理组,以及回调中禁止做的事。
命名管道实务 ── 从设计到安全的 Windows 标准 IPC
以实务视角讲解 Windows 标准进程间通信——命名管道。根据一手资料整理字节模式与消息模式的选择、同时处理多客户端的服务器设计、ACL 与模拟的安全性,以及 .NET 的命名管道流。
Windows的「内存使用量」究竟表示什么 ── 正确解读 Working Set・Private Bytes・Commit・页面文件
任务管理器中的内存、Working Set、Private Bytes、Commit并不是同一个值。本文讲解Windows虚拟内存与物理内存的关系、页面文件的作用,以及在排查内存不足或泄漏时应该关注的指标。
相关主题
与本文相近的主题页面。以本文为起点,可以进一步了解相关服务和其他文章。
Windows 技术主题
汇整 KomuraSoft LLC 关于 Windows 开发、故障调查与既有资产活用文章的主题中心。
常见问题
汇总了咨询这一主题时常见的问题。
- 启用 Hyper-V 后,主机 Windows 实际在哪里运行?
- 虚拟机监控程序直接控制物理 CPU 和内存如何分配,主机 Windows 运行在称为根分区的特殊分区里。物理设备的控制通常由根分区一侧的驱动程序承担。根分区持有设备驱动程序和虚拟化管理栈,但物理 CPU 的所有权属于虚拟机监控程序。
- 任务管理器的「虚拟化: 已启用」是指 Hyper-V 正在运行吗?
- 不是。那一显示表示 CPU 的虚拟化扩展(Intel VT-x/AMD-V)是否已在固件中启用。要看虚拟机监控程序是否实际在运行,请看 systeminfo 中的「A hypervisor has been detected」,或检查 Win32_ComputerSystem.HypervisorPresent。
- 从未创建过虚拟机,为什么虚拟机监控程序还在运行?
- 在 Windows 11 上,基于虚拟化的安全性(VBS)在满足条件的设备上默认启用——例如在兼容硬件上全新安装——而 VBS 建立在 Windows 虚拟机监控程序之上。使用 WSL2 或 Windows Sandbox 时也是如此。与是否有人使用虚拟机无关,虚拟机监控程序在运行并不少见。
- SLAT 是什么,为什么 Hyper-V 需要它?
- SLAT(Second Level Address Translation)是 CPU 把客户机物理地址转换成实际物理地址的机制;Intel EPT 和 AMD RVI 是其实现。没有它,虚拟机监控程序就必须用软件维护转换表,从性能上看不现实,因此现行 Hyper-V 把它当作硬性要求。
- 启用 Hyper-V 后,VirtualBox 和 VMware 会停止工作吗?
- 因为虚拟机监控程序独占使用 CPU 的虚拟化扩展,第三方虚拟机监控程序无法按传统方式运行。不过现行 VirtualBox 和 VMware 有在 Windows 虚拟机监控程序之上运行的模式(经 Windows Hypervisor Platform),因此各自的较新版本可以共存。