更新记录(仅首版,2026年08月22日 发布)
- 首次发布
引用本文(DOI(已登记存档): 10.5281/zenodo.22176857)
以下 DOI 指向先前登记的存档,内容可能与当前正文不同。引用当前正文时,请使用本页网址。
Go Komura(2026)。《Windows 虚拟化的深层(第 1 回)── 你的 Windows 究竟运行在哪里:虚拟机监控程序与分区》。小村软件有限公司。 https://comcomponent.com/zh-CN/blog/windows-virtualization-internals-hypervisor/
- DOI(已登记存档)
- 10.5281/zenodo.22176857
- DOI(上次登记版本)
- 10.5281/zenodo.22176858
明明一台虚拟机都没有创建过,Windows 11 的系统信息(msinfo32)里却写着「基于虚拟化的安全性: 正在运行」。这一行显示到底意味着什么?
在那台 PC 上,主机 Windows 自身已经运行在虚拟机监控程序之上了。 在 Windows 11 上,凡是满足条件的配置——例如在受支持的硬件上全新安装——VBS 都会默认启用,即使不创建虚拟机,这个底座也在被使用。1 WSL2 与 Windows Sandbox 用的也是同一个 Windows 虚拟机监控程序。
第 1 回要从 CPU、内存、设备 I/O 的职责划分出发,说明「启用 Hyper-V 之后,主机 Windows 最终会运行在哪里」。这一回先把「在 Windows 之上装一个虚拟机软件」这种看法重新捋一遍。
「Windows 虚拟化的深层」全 3 回
我们按照底座 → 安全隔离 → 轻量虚拟机的应用这个顺序,来看同一个 Windows 虚拟机监控程序。
| 回次 | 核心问题 |
|---|---|
| 第 1 回: 虚拟机监控程序与分区(本文) | 主机 Windows 运行在哪里 |
| 第 2 回: VBS、HVCI 与 Credential Guard | 连内核都读不到的秘密该放在哪里 |
| 第 3 回: WSL2、Windows Sandbox 与容器 | 保持隔离的同时,为什么还能做得这么轻 |
本文的前提
| 项目 | 内容 |
|---|---|
| 目标读者 | 想弄清 Hyper-V、WSL2、Windows Sandbox 脚下机制的开发者与运维人员 |
| 前提环境 | x64 的 Windows 10/11 或现行 Windows Server。文中对特权环、VT-x/AMD-V、EPT/RVI 的说明均以 x64 为前提,Arm64 使用异常级别等另一套机制 |
| 前提知识 | 能区分内核模式与用户模式。不需要虚拟机运维经验,也不需要虚拟机监控程序的开发知识 |
| 难度与范围 | 中级。只涉及 CPU 虚拟化辅助功能的概念,不深入指令集细节 |
本文的读法
| 想了解的内容 | 该读的小节 |
|---|---|
| Windows 与虚拟机的位置关系、CPU 的执行、职责划分 | 第 1 节的全局图 → 第 2 节的 CPU → 第 3 节的分区 |
| 内存与设备 I/O 由谁居中转达 | 第 4 节的 SLAT → 第 5 节的 VMBus |
| 对不创建虚拟机的 PC 有何影响,如何检查自己的 PC | 第 6 节的日常功能与共存 → 第 7 节的确认方法 |
下面的知识图谱是各种关系的一览表。如果是初次阅读,请从第 1 节的全局图开始顺着正文往下读。
图中实线表示始终成立的关系,虚线表示带条件的关系(成立条件写在详情页各关系的说明中)。关系的完整列表(共 22 条,附依据与确信度)以及主要概念的定义,汇总在知识地图详情页(日文)。数据:JSON-LD / Turtle
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 看 ── 特权环下面还有一层特权
谈 CPU 时,要把区分内核与应用的特权环和区分虚拟机监控程序与客户机的执行模式分开。本节要回答的问题是:「客户机的内核也跑在环 0,为什么不会互相冲突」。
2.1. 特权环保护回顾
x64 的 CPU 有特权级别(环),Windows 让内核模式跑在环 0、用户模式跑在环 3。应用程序之所以不能直接触碰硬件,是因为环 3 无法执行特权指令。
那么,要让多个跑在环 0 的操作系统内核安全地共处于同一颗物理 CPU 之上,该怎么做呢?每一个内核在编写时都认定「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 虚拟化辅助功能在传统特权环之外,另开一个维度,添加了「虚拟机监控程序用的执行模式」与「客户机用的执行模式」。它有时被俗称为「环 -1」,是比环 0 更强的特权。
- 客户机的内核照旧跑在环 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. 分区 ── 隔离的单位
下面细看全局图中相当于「盒子」的分区。这里要区分开的是虚拟机监控程序直接负责的 CPU 与内存调度,以及通常由根分区居中转达的设备 I/O。
3.1. 只有根分区才有的职责
分区是虚拟机监控程序提供的逻辑隔离单位。2 不过,各个分区并不对等。有些东西只有根分区才有。
对物理设备的直接访问
磁盘、网卡、GPU 等设备的驱动程序,由根分区内的 Windows 持有,而不是虚拟机监控程序。另外,Windows Server 的 Hyper-V 支持把特定的 PCIe 设备直接分配给子分区(离散设备分配),此时根分区会交出该设备(客户端版 Windows 无法使用该功能)。4
虚拟化管理栈
掌管虚拟机创建、启动、停止的 VMMS(虚拟机管理服务),以及每台虚拟机各自启动的工作进程(vmwp.exe),都跑在根分区的用户模式中。5 它们属于 Hyper-V 的虚拟机管理功能,因此在那些只为 VBS 或 WSL2 而运行虚拟机监控程序的主机上,可能并不存在。
创建子分区的权限
根分区通过超级调用 API(面向虚拟机监控程序的调用接口)来创建子分区。2
这样的设计是有理由的。如果把各种设备驱动程序都塞进虚拟机监控程序本体,虚拟机监控程序就会变得臃肿,缺陷和攻击入口也随之增多。虚拟机监控程序只专注于 CPU 与内存调度这份最小限度的工作,设备方面的杂事交给根分区里的 Windows。正是这样的职责划分,撑起了 Hyper-V 的「薄」。
flowchart TB
accTitle: 根分区与子分区的职责划分
accDescr: 根分区持有虚拟化管理栈与物理设备驱动程序并通过超级调用创建子分区,子分区在常规配置下只看得到虚拟设备,而在面向 Windows Server 的离散设备分配中则直接访问被分配的设备
subgraph rootp ["根分区"]
vmms["VMMS 与工作进程"]
drv["物理设备驱动程序"]
end
subgraph childp ["子分区"]
gos["客户机操作系统"]
vdev["常规配置下只看得到虚拟设备"]
end
vmms -->|通过超级调用创建与管理| childp
hv2["虚拟机监控程序(只专注于 CPU 与内存调度)"] --- rootp
hv2 --- childp
图 6:把设备驱动程序与管理栈放在根分区一侧,虚拟机监控程序本体就能保持轻薄。
3.2. 从子分区看到的世界
在常规的虚拟设备配置下,子分区里的客户机操作系统看不到物理硬件(唯一的例外是上一小节提到的、面向 Windows Server 的离散设备分配所分配的设备)。它能看到的是虚拟处理器、(看上去)专属于自己的内存空间,以及虚拟设备。对虚拟设备的请求会经由 VMBus 或虚拟机监控程序转发给根分区。2
另一方面,CPU 时间的分配与 SLAT 的内存转换不经过根分区,由虚拟机监控程序直接负责。根分区居中转达的是设备 I/O,而不是全部物理资源。
flowchart TB
accTitle: 从子分区看到的世界
accDescr: 客户机操作系统看得到的是虚拟处理器、分区私有的内存空间与虚拟设备,对虚拟设备的请求经 VMBus 等转发给根分区,CPU 时间与内存转换由虚拟机监控程序直接负责,而在面向 Windows Server 的离散设备分配配置中只对被分配的设备直接访问
gos2["子分区的客户机操作系统"] --> vcpu["虚拟处理器"]
gos2 --> gpa2["私有的内存空间"]
gos2 --> vdev2["虚拟设备"]
vdev2 -->|"经 VMBus 等转发"| rootx["转发给根分区"]
gos2 -.->|直接看不到| phys2["物理 CPU、RAM、真实设备"]
phys2 -.-> dda2["DDA 配置(Windows Server)下只直接访问被分配的设备"]
vcpu ~~~ phys2
图 7:在常规的虚拟设备配置下,客户机看到的一切都是虚拟的窗口,通往物理的通道都要过调度者这一关,只有 Windows Server 的 DDA 所分配的设备才是例外。
这里的关键在于,对跑在主机 Windows 上的应用程序来说,这个结构几乎是透明的。无论是 Win32 API 的调用还是缺页异常的处理,照旧由根分区内的 Windows 内核完成。虚拟机监控程序只在碰上已设定的拦截对象或异常时才会介入。
4. 从内存看 ── 地址转换又多了一级
在内存这一侧,要把客户机认为的「物理」地址与真实 RAM 上的位置分开。请记住GVA → GPA → SPA这个顺序,以及每一级转换的管理者。
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(扩展页表)与 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 与两种设备
设备 I/O 的路径与 CPU 时间、内存转换不同。下面比较模仿真实硬件的做法,和使用虚拟化专用通道的做法。
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 抵达主机的全过程
客户机操作系统的存储请求,按下面的顺序流动。
- 客户机应用的 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. 为什么不用虚拟机的人也不能置身事外
6.1. VBS、WSL2、Sandbox 用的是同一个底座
到这里为止的结构,看上去也许像是「给要架虚拟机的人看的」。但正如开头所说,在现在的 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:底座只有一个,「虚拟化是用虚拟机的人的事」这一前提就此被这张图推翻。
6.2. 与第三方虚拟化软件的共存
还有一个在实务中经常踩到的,是与第三方虚拟化软件的共存。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. 用自己的眼睛确认
自己的 PC 上虚拟机监控程序有没有在运行,在手边就能确认。
7.1. 用 PowerShell 确认虚拟机监控程序与 VBS
先看不需要管理员权限就能执行的确认方法。
# 是否运行在虚拟机监控程序之上
(Get-CimInstance Win32_ComputerSystem).HypervisorPresent
# VBS 的状态(与 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 就在根分区之中——要像这样结合执行环境一起解读。
7.2. 用 systeminfo 区分「运行中」与「事前要求」
接下来是命令提示符下的老办法。
systeminfo
看输出末尾的「Hyper-V 要求」。在虚拟机监控程序尚未运行的机器上,会逐条显示是否支持 SLAT、虚拟化辅助功能是否启用等要求。而在虚拟机监控程序已经运行的机器上,取代要求列表的是仅仅一行「检测到虚拟机监控程序。将不显示 Hyper-V 所需的功能。」。4
也就是说,这一行是你的 Windows 正运行在某个虚拟机监控程序之上的宣告。与 HypervisorPresent 一样,物理 PC 就是在根分区之中,虚拟机之中就是作为子分区——这样的区分解读是必要的。
即便 systeminfo 的要求全是「是」,那也只表示硬件一侧准备就绪。Hyper-V 功能本身可在 Pro、Enterprise、Education 版中使用,Home 版没有。10
7.3. 在界面上查看时,也要分清自己确认的是哪一项
用图形界面的话,就在 msinfo32 的「系统摘要」里查看「基于虚拟化的安全性」那一行。请留意,任务管理器 CPU 栏里的「虚拟化: 已启用」只表示固件中虚拟化辅助功能是否启用,与虚拟机监控程序是否正在运行是两回事。
flowchart TB
accTitle: 虚拟机监控程序运行状态的确认步骤
accDescr: systeminfo 如果显示检测到虚拟机监控程序,就说明正运行在虚拟机监控程序之上(物理 PC 则为根分区);如果显示 Hyper-V 要求一览,就说明尚未运行,需要确认 SLAT、VM 监视器模式扩展、DEP 等全部要求,而即使全部要求都是是,那也只是硬件一侧的准备,Hyper-V 功能还有版本要求
start2["执行 systeminfo"] --> q1{"Hyper-V 要求那一栏是什么?"}
q1 -->|检测到虚拟机监控程序| running["虚拟机监控程序运行中(物理 PC 则在根分区内)"]
q1 -->|逐条列出要求| notyet["虚拟机监控程序尚未运行"]
notyet --> q2{"要求是否全为「是」?"}
q2 -->|全是| can["硬件一侧的准备已经就绪"]
can -.-> ed["Hyper-V 还需要 Pro/Enterprise/Education"]
q2 -->|有否| uefi["在 UEFI/BIOS 等处确认相应项目"]
图 14:systeminfo 的「Hyper-V 要求」栏一个人身兼两职,既确认运行状态,也确认事前要求。
8. 实务中要避免的三种误读
8.1. 「我们没启用 Hyper-V,所以虚拟化跟自家 PC 没关系」
即便没有启用 Hyper-V 功能(管理工具与虚拟机执行环境),只要 VBS 处于启用状态,Windows 虚拟机监控程序就在运行。排查驱动程序兼容性问题、做性能验证、追第三方虚拟化软件的故障时,要确认的不是功能的启用状态,而是 HypervisorPresent 与 VBS 的运行状态。
8.2. 「任务管理器里写着『虚拟化: 已启用』,所以 Hyper-V 在运行」
那一行显示说的是固件设置(VT-x/AMD-V 是否可用)。虚拟机监控程序的运行状态要靠 systeminfo 的「检测到虚拟机监控程序」来判断。反过来,如果任务管理器里显示「已禁用」,那么 Hyper-V 和 WSL2 都无法启用,得先去检查 UEFI/BIOS 的设置。
flowchart TB
accTitle: 三个容易混淆的确认项目
accDescr: 任务管理器的虚拟化栏表示固件设置,Windows 功能列表表示安装状态,systeminfo 与 HypervisorPresent 表示运行状态,它们各自回答的是不同的问题
q3{"想知道什么?"} --> a3["固件中虚拟化辅助功能是否启用"]
q3 --> b3["有没有装上 Hyper-V 功能"]
q3 --> c3["虚拟机监控程序现在是否在运行"]
a3 -.-> a3t["任务管理器的 CPU 栏"]
b3 -.-> b3t["Windows 功能的启用界面"]
c3 -.-> c3t["systeminfo 与 HypervisorPresent"]
图 15:这是三个彼此独立的问题,从其中任何一个显示去推测另外两个,都会变成误读。
8.3. 「虚拟机慢是客户机操作系统的问题」
合成设备的 I/O 要经过 VMBus 交给根分区的 VSP,再经由根分区一侧的设备/后端栈(物理驱动程序之外,还有虚拟交换机与虚拟磁盘的处理)。只盯着客户机内部的计数器,如果瓶颈在主机侧的存储或网卡上,是找不出来的。虚拟机的性能问题,原则上要从客户机与主机(根分区)两侧同时观测。
9. 小结
- 启用 Hyper-V 之后,虚拟机监控程序跑在硬件正上方,主机 Windows 作为根分区运行。2
- 客户机操作系统的内核照旧跑在环 0,只有被设定为拦截对象的操作与异常才会通过 VM Exit 交给虚拟机监控程序。普通的内存访问经 SLAT 转换直接放行。
- 只有根分区持有物理设备驱动程序与虚拟化管理栈,并通过超级调用创建子分区。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 处理,模拟设备与离散设备分配则另有路径
up["根分区与子分区"] --> hvS["虚拟机监控程序"]
hvS --> cpuS["CPU: 分配虚拟处理器"]
hvS --> memS["内存: 用 SLAT 做两级转换"]
hvS --> devS["设备: 合成设备经 VMBus 转发"]
cpuS -.-> cpuN["VM Exit 只在需要介入时发生"]
devS --> vspS["由根分区一侧的 VSP 处理"]
devS -.-> devN["模拟设备与 DDA 另有路径"]
图 16:CPU 的调度与内存转换由虚拟机监控程序直接承担(VM Exit 只在需要介入时发生),合成设备的 I/O 则在 VMBus 的另一端由根分区(VSP)居中转达。
接下来是第 2 回「连内核也看不到的内存 ── VBS、HVCI 与 Credential Guard」。
我们会回收本文埋下的伏笔——虚拟机监控程序握着 SLAT 转换表——去追 Windows 是如何造出「管理员权限也好、内核也好都读不到的内存」的。
相关文章
- Windows 内存的深层(第 1 回)── 虚拟地址变成物理 RAM 的那一刻: 缺页异常的来龙去脉
- Windows 的「内存使用量」到底表示什么 ── 正确解读工作集、Private Bytes、提交量与页面文件
- 用 Windows Sandbox 搭建业务应用验证环境
- Windows 的 P/E 核心与处理器调度
相关咨询领域
小村软件有限公司承接 Windows 应用程序验证环境的设计、虚拟化环境下的性能调查,以及驱动程序与外围设备兼容性问题的分析。
参考链接
-
Microsoft Learn, Silicon assisted security. 关于 VBS 使用硬件虚拟化把安全内核与普通操作系统隔离开,以及 Windows 11 的全新安装在满足前提条件的设备上会默认启用 VBS 与 HVCI 的说明。 ↩ ↩2 ↩3
-
Microsoft Learn, Hyper-V Architecture. 关于虚拟机监控程序把分区作为隔离单位提供、根分区通过超级调用 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 监视器模式扩展、可在 systeminfo 的「Hyper-V 要求」栏确认要求是否满足、虚拟机监控程序运行期间会显示「检测到虚拟机监控程序」,以及可用离散设备分配把特定设备直接分配给子分区的说明。 ↩ ↩2 ↩3 ↩4
-
Microsoft Learn, Appendix B: Hyper-V Architecture and Feature Overview. 关于 VMMS(虚拟机管理服务)负责子分区中虚拟机的状态管理,以及每台虚拟机都会在根分区的用户模式下启动一个工作进程(VMWP)的说明。 ↩
-
Microsoft Learn, Comparing WSL Versions. 关于 WSL2 在轻量实用虚拟机中运行真正的 Linux 内核,以及与现行 VMware、VirtualBox 并用时需要留心之处的说明。 ↩
-
Microsoft Learn, Windows Sandbox architecture. 关于 Windows Sandbox 是把容器技术与虚拟机监控程序的隔离结合起来的轻量 Windows 环境的说明。 ↩
-
Microsoft Learn, Windows Hypervisor Platform. 关于为第三方虚拟化栈提供了在 Windows 虚拟机监控程序之上创建与管理分区的用户模式 API 的说明。 ↩
-
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 的结构。
为什么“剩余1秒”迟迟不结束?── 进度条与剩余时间的工作原理
剩余1秒持续很久、卡在99%、一直显示准备中,分别是怎么回事?从进度的分母、速度预测、最后的处理步骤和界面更新逐一解释,并提供同一任务不同进度显示的交互演示。
Windows 共享文件夹为什么时好时坏——排查 Kerberos、NTLM 与凭据问题
通过症状和日志排查 Windows 共享文件夹时而能访问、时而无法访问的问题。说明 IP 与名称的差异、仅应用失败、空密码、1219、重启及 SMB 签名的检查步骤,以及每项结果能证明什么。
同样是 1GB,为什么复制照片文件夹比复制一部视频还慢?
图解 Windows 中容量相同、复制耗时却不同的原因。梳理文件数量、SSD 与 NAS 的等待时间、打包成 ZIP 的效果、把创建·传输·解压都算进去的对比步骤,以及 robocopy 的适用场景。
相关主题
与本文相近的主题页面。以本文为起点,可以进一步了解相关服务和其他文章。
Windows 技术主题
汇整 KomuraSoft LLC 关于 Windows 开发、故障调查与既有资产活用文章的主题中心。
常见问题
汇总了咨询这一主题时常见的问题。
- 启用 Hyper-V 之后,主机 Windows 究竟运行在哪里?
- 虚拟机监控程序直接控制物理 CPU 与内存的分配,主机 Windows 运行在一个称为根分区的特殊分区之中。物理设备的控制通常由根分区一侧的驱动程序承担。根分区持有设备驱动程序与虚拟化管理栈,但物理 CPU 的支配权在虚拟机监控程序一侧。
- 任务管理器里的「虚拟化: 已启用」是不是表示 Hyper-V 正在运行?
- 不是。那一行显示的是固件中是否启用了 CPU 的虚拟化辅助功能(Intel VT-x/AMD-V)。虚拟机监控程序是否真的在运行,要通过 systeminfo 中「检测到虚拟机监控程序」的显示,或者 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),只要双方都是较新版本就可以共存。