更新紀錄(僅初版,2026年08月22日 發布)
- 初次發布
引用本文(DOI(已登錄存檔): 10.5281/zenodo.22176859)
以下 DOI 指向先前登錄的存檔,內容可能與目前正文不同。引用目前正文時,請使用本頁網址。
Go Komura(2026)。〈Windows 虛擬化的深層(第 1 回)── 你的 Windows 究竟跑在哪裡:Hypervisor 與分割區〉。小村軟體有限公司。 https://comcomponent.com/zh-TW/blog/windows-virtualization-internals-hypervisor/
- DOI(已登錄存檔)
- 10.5281/zenodo.22176859
- DOI(上次登錄版本)
- 10.5281/zenodo.22176860
明明一台虛擬機器都沒建立過,Windows 11 的系統資訊(msinfo32)裡卻寫著「虛擬化型安全性: 執行中」。這一行顯示到底代表什麼?
在那台 PC 上,主機 Windows 本身已經跑在 Hypervisor 之上了。 在 Windows 11 上,凡是符合條件的組態——例如在受支援的硬體上全新安裝——VBS 都會預設啟用,就算不建立虛擬機器,這個基礎也已經在用了。1 WSL2 與 Windows Sandbox 用的也是同一個 Windows Hypervisor。
第 1 回要從 CPU、記憶體、裝置 I/O 的職責分工出發,說明「啟用 Hyper-V 之後,主機 Windows 最後會跑在哪裡」。這一回先把「在 Windows 上面裝一套虛擬機器軟體」這種看法重新整理一遍。
「Windows 虛擬化的深層」全 3 回
我們照著基礎 → 安全性隔離 → 輕量虛擬機器的應用這個順序,來看同一個 Windows Hypervisor。
| 回次 | 核心問題 |
|---|---|
| 第 1 回: Hypervisor 與分割區(本文) | 主機 Windows 跑在哪裡 |
| 第 2 回: VBS、HVCI 與 Credential Guard | 連核心都讀不到的祕密該放在哪裡 |
| 第 3 回: WSL2、Windows Sandbox 與容器 | 在維持隔離的前提下,為什麼還能做得這麼輕 |
本文的前提
| 項目 | 內容 |
|---|---|
| 目標讀者 | 想弄懂 Hyper-V、WSL2、Windows Sandbox 腳下機制的開發者與維運人員 |
| 前提環境 | x64 的 Windows 10/11 或現行 Windows Server。文中對 ring、VT-x/AMD-V、EPT/RVI 的說明都以 x64 為前提,Arm64 使用例外層級等另一套機制 |
| 前提知識 | 能分辨核心模式與使用者模式。不需要虛擬機器的維運經驗,也不需要 Hypervisor 的開發知識 |
| 難度與範圍 | 中階。只處理 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 與記憶體的就是 Hypervisor,而主機 Windows 是以「根分割區」這個名字、作為擁有特權的第一個分割區,跑在它之上。
Hypervisor 是夾在硬體與作業系統之間的一層薄軟體,它建立稱為「分割區」的隔離執行環境,並居中協調對硬體的存取。2 主機 Windows 進入的是根分割區,虛擬機器進入的是子分割區。
根分割區確實受到特別待遇(它擁有對實體裝置的直接存取權與管理堆疊),但就「並未直接支配實體 CPU」這一點而言,它和子分割區站在同樣的位置。
flowchart TB
accTitle: 啟用 Hyper-V 之後的整體結構
accDescr: 實體硬體的正上方是 Hypervisor,其上並列著容納主機 Windows 的根分割區與容納虛擬機器的各個子分割區
hw["實體硬體"] --> hv["Hypervisor"]
hv --> root["根分割區(主機 Windows)"]
hv --> child1["子分割區(各個虛擬機器)"]
root -.-> stack["持有虛擬化管理堆疊與裝置驅動程式"]
圖 1:Hyper-V 不是「Windows 上面的虛擬機器軟體」,而是墊進 Windows 底下的一層,主機作業系統本身就跑在根分割區之中。
你或許會想:「啟用前後的體感毫無差別,真的發生了這麼大的翻轉嗎?」確實發生了。也正因為如此,這個結構平常才不會被察覺。本文會把這一張圖,從 CPU、記憶體、裝置 I/O 三個方向拆開來看。
2. 從 CPU 來看 ── ring 底下還有一層特權
談 CPU 時,要把區分核心與應用程式的 ring和區分 Hypervisor 與客體的執行模式分開。本節要回答的問題是:「客體的核心也跑在 ring 0,為什麼不會互相衝突」。
2.1. ring 保護機制回顧
x64 的 CPU 有特權層級(ring),Windows 讓核心模式跑在 ring 0、使用者模式跑在 ring 3。應用程式之所以不能直接碰硬體,是因為 ring 3 無法執行特權指令。
那麼,要讓多個跑在 ring 0 的作業系統核心安全地共處在同一顆實體 CPU 上,該怎麼做?每一個核心在撰寫時都認定「CPU 由我支配」。把 ring 0 交給所有人就會衝突,不交則誰都跑不起來。
flowchart TB
accTitle: 多個作業系統核心都要求 ring 0 的問題
accDescr: 主機與客體的核心都以擁有 ring 0 全部權限為前提撰寫,光靠傳統的 ring 階梯無法讓它們安全地共處在同一顆實體 CPU 上
k1["主機的核心(以 ring 0 為前提)"] --> want["要求實體 CPU 的支配權"]
k2["客體的核心(以 ring 0 為前提)"] --> want
want --> conflict["光靠傳統 ring 無法兩全"]
conflict --> need["需要比 ring 0 更上層的協調者"]
圖 2:ring 的階梯是照著只有一個作業系統來設計的,要讓多個核心共處,就得再往上加一層特權。
2.2. 虛擬化擴充功能 ── Hypervisor 專用模式
解開這道題的,是 CPU 的虛擬化擴充功能(Intel VT-x/AMD-V)。Hyper-V 把具備這項功能的處理器列為必要條件。2 虛擬化擴充功能在傳統 ring 之外另闢一個軸線,加上了「Hypervisor 用的執行模式」與「客體用的執行模式」。它有時被俗稱為「ring -1」,是比 ring 0 更強的特權。
- 客體的核心照舊跑在 ring 0,不需要改寫。
- 只不過那個 ring 0 是「客體模式中的 ring 0」,並不支配整顆實體 CPU。
- 當客體碰上需要 Hypervisor 介入的特定操作(被設定為攔截對象的指令,或是例外、違規)時,CPU 會自動把控制權交給 Hypervisor(VM Exit)。Hypervisor 處理完之後,再把控制權還給客體(VM Entry)。只要 SLAT 的轉譯走得通,一般的記憶體存取就不會觸發 VM Exit,直接放行。
中斷也一樣。分割區不會直接碰實體處理器,中斷由 Hypervisor 接收之後再分派給各個分割區。2
flowchart TB
accTitle: 客體執行與 VM Exit 的流程
accDescr: 客體的核心與應用程式跑在客體模式的 ring 0 與 ring 3,一般記憶體存取靠 SLAT 的轉譯直接放行,而碰上被設定為攔截對象的操作或例外時則以 VM Exit 把控制權交給 Hypervisor,處理完再用 VM Entry 回到客體
guest["正在客體模式中執行(含 ring 0 的核心)"] --> op{"是否需要介入的操作?(已設定的攔截、例外)"}
op -->|否| cont["就這樣繼續執行"]
op -->|是| exitEv["VM Exit(CPU 交出控制權)"]
exitEv --> hvp["Hypervisor 進行處理"]
hvp --> entry["以 VM Entry 回到客體"]
entry --> guest
圖 3:客體作業系統不必改寫、照舊跑在 ring 0,只有必要時 CPU 才會去叫 Hypervisor。
這樣的一來一回,和記憶體系列文章追過的「因分頁錯誤進入核心,再回到同一道指令」的流程非常相似。CPU 藉由例外與轉移機制攔下控制權,交給上層的管理者判斷之後再還回原處。在 Windows 的深層,這種形態會一再出現。
2.3. Type 1 與 Type 2 ── 差別在於裝在哪一層
Hypervisor 大致可分為直接跑在硬體上的 Type 1(裸機型)與跑在主端作業系統上的 Type 2(主端型)。Hyper-V 屬於 Type 1。3 VirtualBox 以及(單獨執行時的)VMware Workstation 歸為 Type 2。
一聽到 Type 1,容易聯想成「沒有主端作業系統的伺服器專用組態」,但 Hyper-V 的情形並非如此。主機 Windows 並沒有消失,而是「搬家」搬進了根分割區。啟用 Hyper-V 並重新開機後,開機過程中會先啟動 Hypervisor,主機 Windows 再以根分割區的身分在其上啟動。
flowchart TB
accTitle: Type 1 與 Type 2 Hypervisor 的差別
accDescr: Type 2 是硬體上面有主端作業系統,其上再裝 Hypervisor 與虛擬機器;而 Type 1 的 Hyper-V 是硬體正上方就是 Hypervisor,主端作業系統也進到其上的根分割區
subgraph t2 ["Type 2(主端型)"]
hw2["硬體"] --> hostos["主端作業系統"]
hostos --> hv2["Hypervisor"]
hv2 --> vm2["虛擬機器"]
end
subgraph t1 ["Type 1(Hyper-V)"]
hw1["硬體"] --> hv1["Hypervisor"]
hv1 --> root1["根分割區(主端作業系統)"]
hv1 --> vm1["虛擬機器"]
end
vm2 ~~~ hw1
圖 4:Type 2 是 Hypervisor 裝在主端作業系統上面,而 Type 1 的 Hyper-V 順序反了過來,主端作業系統自己裝在下面那一層之上。
把啟用前後發生的變化擺到開機的時間軸上看,就是下面這樣。
flowchart TB
accTitle: 啟用 Hyper-V 之後的開機順序
accDescr: 開機通電之後,開機過程中先啟動 Hypervisor,主機 Windows 再以根分割區的身分在其上啟動,虛擬機器與 VBS 等則在更後面才開始
poweron["通電、開始開機"] --> bhv["Hypervisor 先啟動"]
bhv --> broot["主機 Windows 以根分割區的身分啟動"]
broot --> blater["虛擬機器、VBS、WSL2 等在其上啟動"]
broot -.-> feel["使用者的體感一如往常"]
圖 5:在登入畫面出現之前,順序的翻轉就已經結束,主端作業系統從一開始就跑在 Hypervisor 之上。
3. 分割區 ── 隔離的單位
接著細看全貌圖中相當於「盒子」的分割區。這裡要分開的是Hypervisor 直接負責的 CPU 與記憶體協調,以及通常由根分割區居中傳遞的裝置 I/O。
3.1. 只有根分割區才有的職責
分割區是 Hypervisor 提供的邏輯隔離單位。2 不過,各個分割區並不對等。有些東西只有根分割區才有。
對實體裝置的直接存取
磁碟、網路卡、GPU 等裝置的驅動程式,是由根分割區內的 Windows 持有,而不是 Hypervisor。另外,Windows Server 的 Hyper-V 有把特定 PCIe 裝置直接指派給子分割區的組態(離散裝置指派),此時根分割區會放掉該裝置(用戶端版 Windows 無法使用)。4
虛擬化管理堆疊
掌管虛擬機器建立、啟動、停止的 VMMS(虛擬機器管理服務),以及每台虛擬機器各自啟動的工作者處理程序(vmwp.exe),都跑在根分割區的使用者模式中。5 它們屬於 Hyper-V 的虛擬機器管理功能,因此在那些只為了 VBS 或 WSL2 而執行 Hypervisor 的主機上,可能並不存在。
建立子分割區的權限
根分割區透過 Hypercall API(對 Hypervisor 的呼叫介面)來建立子分割區。2
這樣的設計是有理由的。如果把各式各樣的裝置驅動程式都塞進 Hypervisor 本體,Hypervisor 就會變得龐大,缺陷與攻擊入口也跟著變多。Hypervisor 只專注在 CPU 與記憶體協調這份最小限度的工作,裝置方面的雜事就交給根分割區裡的 Windows。正是這樣的分工,撐起了 Hyper-V 的「薄」。
flowchart TB
accTitle: 根分割區與子分割區的職責分工
accDescr: 根分割區持有虛擬化管理堆疊與實體裝置驅動程式並透過 Hypercall 建立子分割區,子分割區在一般組態下只看得到虛擬裝置,而在給 Windows Server 用的離散裝置指派中則直接存取被指派的裝置
subgraph rootp ["根分割區"]
vmms["VMMS 與工作者處理程序"]
drv["實體裝置驅動程式"]
end
subgraph childp ["子分割區"]
gos["客體作業系統"]
vdev["一般組態下只看得到虛擬裝置"]
end
vmms -->|以 Hypercall 建立與管理| childp
hv2["Hypervisor(只專注在 CPU 與記憶體的協調)"] --- rootp
hv2 --- childp
圖 6:把裝置驅動程式與管理堆疊放在根分割區這一端,Hypervisor 本體就能保持輕薄。
3.2. 從子分割區看到的世界
在一般的虛擬裝置組態下,子分割區裡的客體作業系統看不到實體硬體(唯一的例外是前一小節提到、給 Windows Server 用的離散裝置指派所指派的裝置)。它看得到的是虛擬處理器、(看起來)專屬於自己的記憶體空間,以及虛擬裝置。對虛擬裝置的要求會經由 VMBus 或 Hypervisor 轉送給根分割區。2
另一方面,CPU 時間的配置與 SLAT 的記憶體轉譯不經過根分割區,由 Hypervisor 直接負責。根分割區居中傳遞的是裝置 I/O,而不是所有實體資源。
flowchart TB
accTitle: 從子分割區看到的世界
accDescr: 客體作業系統看得到的是虛擬處理器、分割區私有的記憶體空間與虛擬裝置,對虛擬裝置的要求經 VMBus 等轉送給根分割區,CPU 時間與記憶體轉譯由 Hypervisor 直接負責,而在給 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 核心處理。Hypervisor 只在碰上已設定的攔截對象或例外時才會介入。
4. 從記憶體來看 ── 位址轉譯又多了一層
在記憶體這一側,要把客體認為的「實體」位址與真正 RAM 上的位置分開。請記住GVA → GPA → SPA這個順序,以及每一層轉譯的管理者。
4.1. 三種位址
記憶體系列的第 1 回追過虛擬位址經分頁表轉譯為實體位址的流程(見「虛擬位址變成實體 RAM 的那一瞬間」)。在虛擬化環境中,這個轉譯的底下又多了一層,位址因此變成三種。
| 位址 | 縮寫 | 由誰管理 |
|---|---|---|
| 客體虛擬位址 | GVA | 客體作業系統的分頁表 |
| 客體實體位址 | GPA | 客體深信是「實體」的位址 |
| 系統實體位址 | SPA | Hypervisor(真正 RAM 上的位置) |
客體作業系統用自己的分頁表把 GVA 轉譯成 GPA。但客體看到的 GPA 並不是真正的實體位址,而是各分割區專屬的私有記憶體空間。2 把 GPA 對應到真正 RAM 上的位置(SPA),是 Hypervisor 的工作。
4.2. SLAT ── 用硬體完成兩層轉譯
如果第二層轉譯全靠軟體來做,Hypervisor 就得逐一追蹤客體分頁表的更新,從效能上看並不切實際。於是 CPU 裡準備了用硬體查第二層轉譯表的機制。這就是 SLAT(Second Level Address Translation),Intel EPT(延伸分頁表)與 AMD RVI 都屬於這一類。
現行的 Hyper-V 把支援 SLAT 的 64 位元處理器列為必要條件。4
flowchart TB
accTitle: 由 SLAT 完成的兩層位址轉譯
accDescr: 客體虛擬位址先由客體作業系統的分頁表轉譯為客體實體位址,再由 Hypervisor 管理的 SLAT 轉譯為系統實體位址,最後抵達真正的 RAM
gva["客體虛擬位址(GVA)"] -->|客體作業系統的分頁表| gpa["客體實體位址(GPA)"]
gpa -->|"SLAT(EPT/RVI 的轉譯表)"| spa["系統實體位址(SPA)"]
spa --> ram["實體 RAM"]
gpa -.-> note["只是客體深信是實體的那一層"]
圖 8:客體分頁表底下又插進一層由 Hypervisor 管理的轉譯表,CPU 用硬體把兩者都走一遍。
SLAT 並不只是為了虛擬機器執行效率而存在的功能。第 2 回要看的 VBS,就把「每個特權層級可以擁有各自不同的 SLAT 轉譯表」這個性質,當成建構安全性邊界的材料。之所以能做出連核心都看不到的記憶體,正是因為第二層轉譯握在 Hypervisor 手上。這裡是貫穿整個系列的伏筆,所以請務必記住「轉譯表的管理者是 Hypervisor」這一點。
5. 從裝置 I/O 來看 ── VMBus 與兩種裝置
裝置 I/O 的路徑和 CPU 時間、記憶體轉譯不同。下面比較模仿真實硬體的做法,以及使用虛擬化專用通道的做法。
5.1. 模擬裝置的極限
讓子分割區看到裝置的經典做法,是用軟體完整模仿一個真實存在的硬體(例如老舊的 IDE 控制器)。客體作業系統的標準驅動程式可以直接使用,相容性很高,但客體每敲一次 I/O 連接埠就會產生一次 VM Exit,效能上不去。
flowchart TB
accTitle: 模擬裝置的 I/O 為何緩慢
accDescr: 客體每操作一次 I/O 連接埠就會以 VM Exit 把控制權交給 Hypervisor 這一端,用軟體模仿裝置之後再回到客體,如此往返一再重複因而緩慢
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 上,Hypervisor 已經是日常的一部分。
- 虛擬化型安全性(VBS)。 它用 Windows Hypervisor 做出隔離環境,把安全性功能收在裡面。在 Windows 11 上,符合條件時(例如在受支援的硬體上全新安裝)會預設啟用。1 細節放在第 2 回。
- WSL2。 它在輕量公用程式虛擬機器中執行真正的 Linux 核心。6
- Windows Sandbox。 它是由 Hypervisor 隔離出來的用完即丟的 Windows 環境。7 這兩者都放在第 3 回。
flowchart TB
accTitle: 裝在同一個 Hypervisor 上的日常功能
accDescr: 不只是 Hyper-V 的虛擬機器,在符合全新安裝等條件的裝置上預設啟用的 VBS、WSL2 與 Windows Sandbox,也都以同一個 Windows Hypervisor 為基礎
base["Windows Hypervisor"] --> f1["Hyper-V 的虛擬機器"]
base --> f2["VBS(全新安裝等情況下預設啟用)"]
base --> f3["WSL2"]
base --> f4["Windows Sandbox"]
f2 -.-> daily["不用虛擬機器的 PC 上也在執行的原因"]
圖 12:基礎只有一個,「虛擬化是用虛擬機器的人的事」這個前提就此被這張圖推翻。
6.2. 與第三方虛擬化軟體的共存
另外一個在實務上常踩到的,是與第三方虛擬化軟體的共存。CPU 的虛擬化擴充功能由 Hypervisor 獨占使用,因此在 Windows Hypervisor 正在執行的環境裡,VirtualBox 等軟體無法再以傳統方式(自行使用 CPU 虛擬化擴充功能的方式)執行。
為此微軟準備了名為 Windows Hypervisor Platform 的公開 API,第三方的虛擬化堆疊可以用裝在 Windows Hypervisor 之上的形式運作。8 現行 VirtualBox/VMware 能與 WSL2 共存正是靠這套機制,不過切換方式帶來的效能差異與功能差異,有時會以「啟用 Hyper-V(或 VBS)之後虛擬化軟體的狀況變了」這種形式被觀測到。
flowchart TB
accTitle: CPU 虛擬化擴充功能的擁有者與第三方虛擬化軟體的路徑
accDescr: Windows Hypervisor 執行期間由它獨占 CPU 的虛擬化擴充功能,支援 WHP 的第三方虛擬化軟體經由 Windows Hypervisor Platform 裝在其上執行,而不支援 WHP 的實作則無法執行或功能受限
vt["CPU 的虛擬化擴充功能(VT-x/AMD-V)"] --> hvon{"Windows Hypervisor 是否執行中?"}
hvon -->|否| direct["第三方軟體可以直接使用"]
hvon -->|是| own["由 Hypervisor 獨占"]
own --> whp["Windows Hypervisor Platform"]
whp --> third["支援 WHP 的第三方軟體在其上執行"]
third -.-> nowhp["不支援的實作無法執行或功能受限"]
圖 13:虛擬化擴充功能的擁有者只有一個,在 Hypervisor 執行期間能與它共處的,僅限支援公開 API(WHP)的第三方軟體。
7. 用自己的眼睛確認
自己的 PC 上 Hypervisor 有沒有在執行,在手邊就能確認。
7.1. 用 PowerShell 確認 Hypervisor 與 VBS
先看不需要系統管理員權限就能執行的確認方式。
# 是否跑在 Hypervisor 之上
(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 表明的只是「有沒有跑在 Hypervisor 之上」,它並不區分根分割區還是子分割區。在虛擬機器裡的 Windows 上執行,也會以子分割區的身分回傳 True。如果在實體 PC 上的 Windows 裡回傳 True,那這個 Windows 就在根分割區之中——要像這樣搭配執行環境一起判讀。
7.2. 用 systeminfo 分辨「執行中」與「事前需求」
接著是命令提示字元下的老方法。
systeminfo
看輸出末尾的「Hyper-V 需求」。在 Hypervisor 還沒執行的機器上,會逐項顯示是否支援 SLAT、虛擬化擴充功能是否啟用等需求。而在 Hypervisor 已經執行的機器上,取代需求清單的是只有一行「偵測到 Hypervisor。將不顯示 Hyper-V 所需的功能。」。4
也就是說,這一行是你的 Windows 正跑在某個 Hypervisor 之上的宣告。和 HypervisorPresent 一樣,實體 PC 就是在根分割區之中、虛擬機器之中就是以子分割區的身分——這樣的分辨判讀是必要的。
就算 systeminfo 的需求全部都是「是」,那也只表示硬體端已經準備好了。Hyper-V 功能本身可以在 Pro、Enterprise、Education 版中使用,Home 版沒有。10
7.3. 在畫面上查看時,也要分清自己確認的是哪一項
用圖形介面的話,就在 msinfo32 的「系統摘要」裡確認「虛擬化型安全性」那一行。請注意,工作管理員 CPU 欄裡的「虛擬化: 已啟用」只表示韌體中虛擬化擴充功能是否啟用,和 Hypervisor 是否正在執行是兩回事。
flowchart TB
accTitle: Hypervisor 執行狀態的確認步驟
accDescr: systeminfo 如果顯示偵測到 Hypervisor,就代表正跑在 Hypervisor 之上(實體 PC 則是在根分割區內);如果顯示 Hyper-V 需求清單,就代表還沒執行,要確認 SLAT、VM 監視器模式延伸、DEP 等全部需求,而就算全部需求都是是,那也只是硬體端的準備,Hyper-V 功能還有版本上的需求
start2["執行 systeminfo"] --> q1{"Hyper-V 需求那一欄是什麼?"}
q1 -->|偵測到 Hypervisor| running["Hypervisor 執行中(實體 PC 則在根分割區內)"]
q1 -->|逐項列出需求| notyet["Hypervisor 尚未執行"]
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 Hypervisor 就在執行。追查驅動程式相容性問題、做效能驗證、追第三方虛擬化軟體的故障時,要確認的不是功能的啟用狀態,而是 HypervisorPresent 與 VBS 的執行狀態。
8.2. 「工作管理員上寫著『虛擬化: 已啟用』,所以 Hyper-V 在執行」
那一行顯示講的是韌體設定(VT-x/AMD-V 是否可用)。Hypervisor 的執行狀態要靠 systeminfo 的「偵測到 Hypervisor」來判斷。反過來說,如果工作管理員顯示「已停用」,那麼 Hyper-V 和 WSL2 都無法啟用,得先去檢查 UEFI/BIOS 的設定。
flowchart TB
accTitle: 三個容易混淆的確認項目
accDescr: 工作管理員的虛擬化欄代表韌體設定,Windows 功能清單代表安裝狀態,systeminfo 與 HypervisorPresent 代表執行狀態,它們各自回答的是不同的問題
q3{"想知道什麼?"} --> a3["韌體中虛擬化擴充功能是否啟用"]
q3 --> b3["有沒有裝上 Hyper-V 功能"]
q3 --> c3["Hypervisor 現在是否正在執行"]
a3 -.-> a3t["工作管理員的 CPU 欄"]
b3 -.-> b3t["Windows 功能的啟用畫面"]
c3 -.-> c3t["systeminfo 與 HypervisorPresent"]
圖 15:這是三個彼此獨立的問題,從其中任何一個顯示去推測另外兩個,都會變成誤讀。
8.3. 「虛擬機器慢是客體作業系統的問題」
合成裝置的 I/O 要經過 VMBus 交給根分割區的 VSP,再經由根分割區端的裝置/後端堆疊(實體驅動程式之外,還有虛擬交換器與虛擬磁碟的處理)。只盯著客體內部的計數器,如果瓶頸在主機端的儲存體或網路卡上,是找不出來的。虛擬機器的效能問題,原則上要從客體與主機(根分割區)兩端同時觀測。
9. 總結
- 啟用 Hyper-V 之後,Hypervisor 跑在硬體正上方,主機 Windows 以根分割區的身分運作。2
- 客體作業系統的核心照舊跑在 ring 0,只有被設定為攔截對象的操作與例外才會以 VM Exit 交給 Hypervisor。一般的記憶體存取靠 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,Hypervisor 在執行也並不罕見。1 執行狀態可以用
HypervisorPresent與 systeminfo 確認。
第 1 回的全貌,就濃縮在這一張圖裡。
flowchart TB
accTitle: 第 1 回的全貌
accDescr: 根分割區與子分割區底下是 Hypervisor,CPU 以虛擬處理器的排程來配置(VM Exit 只發生在已設定的攔截與例外上),記憶體由 SLAT 的兩層轉譯來協調,合成裝置的 I/O 經 VMBus 轉送並由根分割區的 VSP 處理,模擬裝置與離散裝置指派則另有路徑
up["根分割區與子分割區"] --> hvS["Hypervisor"]
hvS --> cpuS["CPU: 配置虛擬處理器"]
hvS --> memS["記憶體: 以 SLAT 做兩層轉譯"]
hvS --> devS["裝置: 合成裝置經 VMBus 轉送"]
cpuS -.-> cpuN["VM Exit 只在需要介入時發生"]
devS --> vspS["由根分割區端的 VSP 處理"]
devS -.-> devN["模擬裝置與 DDA 另有路徑"]
圖 16:CPU 的排程與記憶體轉譯由 Hypervisor 直接承擔(VM Exit 只在需要介入時發生),合成裝置的 I/O 則在 VMBus 的另一端由根分割區(VSP)居中傳遞。
接下來是第 2 回「連核心都看不到的記憶體 ── VBS、HVCI 與 Credential Guard」。
我們會回收本文埋下的伏筆——Hypervisor 握著 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. 關於 Hypervisor 把分割區當成隔離單位提供、根分割區透過 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 Hypervisor、根分割區擁有實體 I/O 裝置,以及 VMBus 利用共用記憶體提供高效能分割區間通訊的說明。 ↩ ↩2
-
Microsoft Learn, System requirements for Hyper-V on Windows and Windows Server. 關於必須具備支援 SLAT 的 64 位元處理器與 VM 監視器模式延伸、可在 systeminfo 的「Hyper-V 需求」欄確認需求是否滿足、Hypervisor 執行期間會顯示「偵測到 Hypervisor」,以及可用離散裝置指派把特定裝置直接指派給子分割區的說明。 ↩ ↩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 是把容器技術與 Hypervisor 的隔離結合起來的輕量 Windows 環境的說明。 ↩
-
Microsoft Learn, Windows Hypervisor Platform. 關於為第三方虛擬化堆疊提供了在 Windows Hypervisor 之上建立與管理分割區的使用者模式 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,用 Hypervisor 與 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 究竟跑在哪裡?
- Hypervisor 直接控制實體 CPU 與記憶體的配置,主機 Windows 跑在一個稱為根分割區的特殊分割區之中。實體裝置的控制通常由根分割區端的驅動程式負責。根分割區持有裝置驅動程式與虛擬化管理堆疊,但實體 CPU 的支配權在 Hypervisor 這一端。
- 工作管理員裡的「虛擬化: 已啟用」是不是代表 Hyper-V 正在執行?
- 不是。那一行顯示的是韌體中是否啟用了 CPU 的虛擬化擴充功能(Intel VT-x/AMD-V)。Hypervisor 是否真的在執行,要靠 systeminfo 中「偵測到 Hypervisor」的顯示,或是 Win32_ComputerSystem 的 HypervisorPresent 來確認。
- 一台虛擬機器都沒建立過,為什麼 Hypervisor 還在執行?
- 在 Windows 11 上,凡是符合條件的裝置——例如在受支援的硬體上全新安裝——虛擬化型安全性(VBS)都會預設啟用,而 VBS 以 Windows Hypervisor 為基礎。使用 WSL2 或 Windows Sandbox 時也一樣。與有沒有在用虛擬機器無關,Hypervisor 已經啟動並不罕見。
- SLAT 是什麼?為什麼它是 Hyper-V 的必要條件?
- SLAT(Second Level Address Translation)是由 CPU 完成客體實體位址到真正實體位址轉譯的機制,Intel EPT 與 AMD RVI 都屬於這一類。少了它,Hypervisor 就得用軟體維護轉譯表,從效能上看並不切實際,因此現行 Hyper-V 把它列為必要條件。
- 啟用 Hyper-V 之後,VirtualBox 與 VMware 就不能用了嗎?
- 由於 Hypervisor 會獨占使用 CPU 的虛擬化擴充功能,第三方 Hypervisor 無法再以傳統方式執行。不過現行的 VirtualBox 與 VMware 都具備跑在 Windows Hypervisor 之上的模式(經由 Windows Hypervisor Platform),只要雙方都是較新版本就能共存。