虛擬化的含義豐富,應用廣泛。目前虛擬化技術主要關注于服務器虛擬化,即在一個宿主計算機上提供多個獨立操作系統。本文將探索虛擬化背后的思想,然后討論實現虛擬化的一些技術。我們還將了解現有的其他一些虛擬化技術,例如 Linux 上操作系統的虛擬化。
進行虛擬化 就是要將某種形式的東西以另外一種形式呈現出來。對計算機進行虛擬化就是要將計算機以多臺計算機或一臺完全不同的計算機的形式呈現出來。
虛擬化也可以將多臺計算機組合成一臺計算機的形式呈現出來。這通常稱為服務器聚合或網格計算。
下面讓我們首先來看一下虛擬化的起源。
虛擬化的歷史
虛擬化并不是什么新主題;實際上,它的存在已經超過 40 年了。虛擬化技術最早的一些用法包括 IBM® 7044、麻省理工學院(MIT)在 IBM 704 上開發的 CTSS(Compatible Time Sharing System)以及曼徹斯特大學的 Atlas 項目(世界上最早的超級計算機之一),這些都是請求頁面調度和監管進程調用的先驅。
硬件虛擬化
IBM 早在 20 世紀 60 年代開發 System/360™ Model 67 大型機時就認識到了虛擬化的重要性。Model 67 通過 VMM(Virtual Machine Monitor)對所有的硬件接口都進行了虛擬化。在早期計算中,操作系統被稱為 supervisor。能夠在其他操作系統上運行的操作系統被稱為 hypervisor(這個術語是在 20 世紀 70 年代出現的)。
VMM 可以直接在底層硬件上運行,允許運行多個虛擬機(VM)。每個 VM 都可以運行一個自己私有操作系統的實例 —— 在早些時候,這稱為 CMS(或 Conversational Monitor System)。之后 VM 繼續發展,現在您可以在 System z9™ 大型機上發現 VM。這提供了很好的向后兼容性,甚至是對 System/360 產品線的兼容性。
處理器虛擬化
虛擬化早期的另外一種用法(在本例中是對處理器的仿真)是 P-code(或偽碼)機。P-code 是一種機器語言,運行于虛擬機而不是實際硬件。P-code 早在 20 世紀 70 年代就已在加州大學圣地亞哥分校(UCSD)Pascal 系統上頗有名氣了,它將 Pascal 程序編譯成 P-code,然后在一個 P-code 虛擬機上運行。這就使 P-code 程序具有了高度的可移植性,而且,只要有可用的 P-code 虛擬機,P-code 程序就可以運行。
20 世紀 60 年代對 BCPL(Basic Combined Programming Language)的設計中也采用了相同的概念,C 語言即由 BCPL 發展而來。在這種用法中,編譯器會將 BCPL 代碼編譯成稱為 O-code 的中間機器代碼。接下來的第二個步驟是將 O-code 編譯成目標機器的原始語言。現代編譯器所使用的這種模型為將編譯器移植到新目標體系結構上提供了很大的靈活性(通過一種中間語言將前端和后端分隔開來)。
Java 虛擬機(JVM)
Java™ 語言對自己的虛擬機沿用了這種 P-code 模型。這樣只需要通過簡單地移植 JVM 就可以將 Java 程序廣泛地分布到無數的體系架構上。
指令集虛擬化
虛擬化最新的發展稱為指令集虛擬化,或者二進制轉換。在這種模型中,虛擬指令集被轉換成底層硬件的物理指令集,這個過程通常都是動態的。當代碼執行時,就會對代碼的某個段進行轉換。如果出現分支情況,就會導入新代碼集并進行轉換。這使它與緩存操作非常類似,后者是將指令塊從內存移動到本地快速緩存中執行。
這種模型最近在 Transmeta 設計的 Crusoe 中央處理單元(CPU)中得到了使用。二進制轉換由 Code Morphing 的專利技術實現。類似的一個例子是完全虛擬化解決方案通過運行時代碼掃描來查找和重定向特權指令(用來解決特定處理器指令集的一些問題)。
虛擬化和游戲
一篇有關虛擬化的文章如果不提一下 MAME(Multiple-Arcade Machine Emulator),就不算完整。顧名思義,MAME 就是以前很多 arcade 游戲的一個完整的機器模擬器。除了對這些游戲中使用的處理器進行虛擬化之外,還可以對整個機器進行虛擬化,包括聲音、圖形處理硬件和控制單元。MAME 是一個非常不錯的應用程序,不過要理解它們究竟實現了哪些功能,研讀一下它的源代碼會非常有幫助。
虛擬化的類型
實現虛擬化的方法不止一種。實際上,有幾種方法都可以通過不同層次的抽象來實現相同的結果。本節將介紹 Linux 中常用的 3 種虛擬化方法,以及它們相應的優缺點。業界有時會使用不同的術語來描述相同的虛擬化方法。本文中使用的是最常用的術語,同時給出了其他術語以供參考。
仿真和開發
硬件仿真的應用之一是進行固件和硬件的協作開發。固件開發人員可以使用目標硬件 VM 在仿真環境中對自己的實際代碼進行驗證,而不需要等到硬件實際可用的時候。
硬件仿真
毫無疑問,最復雜的虛擬化實現技術就是硬件仿真。在這種方法中,可以在宿主系統上創建一個硬件 VM 來仿真所想要的硬件,如圖 1 所示。

正如您所能預見的一樣,使用硬件仿真的主要問題是速度會非常慢。由于每條指令都必須在底層硬件上進行仿真,因此速度減慢 100 倍的情況也并不稀奇。若要實現高度保真的仿真,包括周期精度、所仿真的 CPU 管道以及緩存行為,實際速度差距甚至可能會達到 1000 倍之多。
硬件仿真也有自己的優點。例如,使用硬件仿真,您可以在一個 ARM 處理器主機上運行為 PowerPC® 設計的操作系統,而不需要任何修改。您甚至可以運行多個虛擬機,每個虛擬器仿真一個不同的處理器。
完全虛擬化
完全虛擬化(full virtualization),也稱為原始虛擬化,是另外一種虛擬化方法。這種模型使用一個虛擬機,它在客戶操作系統和原始硬件之間進行協調(參見圖 2)。“協調”在這里是一個關鍵,因為 VMM 在客戶操作系統和裸硬件之間提供協調。特定受保護的指令必須被捕獲下來并在 hypervisor 中進行處理,因為這些底層硬件并不由操作系統所擁有,而是由操作系統通過 hypervisor 共享。

雖然完全虛擬化的速度比硬件仿真的速度要快,但是其性能要低于裸硬件,因為中間經過了 hypervisor 的協調過程。完全虛擬化的最大優點是操作系統無需任何修改就可以直接運行。惟一的限制是操作系統必須要支持底層硬件(例如 PowerPC)。
老硬件上的 hypervisor
有些比較老的硬件,例如 x86,會給完全虛擬化帶來一些問題。例如,需要 VMM 處理的一些特定敏感指令并沒有捕獲。因此,hypervisor 必須要動態掃描并捕獲這些特權模式代碼來解決這一問題。
超虛擬化
超虛擬化(paravirtualization)是另外一種流行的虛擬化技術,它與完全虛擬化有一些類似。這種方法使用了一個 hypervisor 來實現對底層硬件的共享訪問,還將與虛擬化有關的代碼集成到了操作系統本身中(參見圖 3)。這種方法不再需要重新編譯或捕獲特權指令,因為操作系統本身在虛擬化進程中會相互緊密協作。

正如前面介紹的一樣,超虛擬化技術需要為 hypervisor 修改客戶操作系統,這是它的一個缺點。但是超虛擬化提供了與未經虛擬化的系統相接近的性能。與完全虛擬化類似,超虛擬化技術可以同時支持多個不同的操作系統。
操作系統級的虛擬化
我們要介紹的最后一種技術是操作系統級的虛擬化,它使用的技術與前面所介紹的有所不同。這種技術在操作系統本身之上實現服務器的虛擬化。這種方法支持單個操作系統,并可以將獨立的服務器相互簡單地隔離開來(參見圖 4)。

操作系統級的虛擬化要求對操作系統的內核進行一些修改,但是其優點是可以獲得原始性能。
為什么虛擬化如此重要?
在了解目前 Linux 可以使用的虛擬化方法之前,讓我們先來了解一下虛擬化的優點。
從商業角度來看,使用虛擬化技術有很多原因。大部分原因都可以歸結于服務器的鞏固(server consolidation)。簡單來說,如果您可以對一個服務器上多個未經充分利用的系統進行虛擬化,由于服務器的數量少了,顯然可以節省大量電力、空間、制冷和管理成本。由于很難確定服務器的利用情況,虛擬化技術支持稱為動態遷移的技術。動態遷移(Live migration)允許操作系統及其應用程序遷移到新的服務器上,從而實現負載在可用硬件上的均衡。
虛擬化技術對于開發人員來說也非常重要。Linux 內核占據了一個單一的地址空間,這意味著內核或任何驅動程序的故障都會導致整個操作系統的崩潰。虛擬化技術意味著您可以運行多個操作系統,如果其中一個系統由于某個 bug 而崩潰了,那么 hypervisor 和其他操作系統都依然可以繼續運行。這可以使內核的調試非常類似于用戶空間應用程序的調試。
與 Linux 有關的虛擬化項目
表 1 給出了幾個 Linux 系統上的虛擬化項目,并著重介紹了其中的開源解決方案。

有關其他解決方案的信息,請參看 參考資料 部分。
庫級虛擬化
盡管在正文中沒有討論,庫級虛擬化是另外一種可以通過庫對操作系統部分進行仿真的虛擬化技術。這種虛擬化技術的例子包括 Wine(Linux 上使用的一個部分 Win32 API)和 LxRun(Solaris 上使用的一個部分 Linux API)。
Bochs(仿真)
Bochs 是一個 x86 計算機仿真器,它在很多平臺上(包括 x86、PowerPC、Alpha、SPARC 和 MIPS)都可以移植和運行。使 Bochs 更為有趣的是它不僅可以對處理器進行仿真,還可以對整個計算機進行仿真,包括計算機的外圍設備,比如鍵盤、鼠標、視頻圖像硬件、網卡(NIC)等。
Bochs 可以配置作為一個老式的 Intel® 386 或其后繼處理器使用,例如 486、Pentium、Pentium Pro 或 64 位處理器。它甚至還可以對一些可選的圖形指令進行仿真,例如 MMX 和 3DNow。
使用 Bochs 仿真器,您可以運行任何 Linux 上的 Linux 發行版、Linux 上的 Microsoft® Windows® 95/98/NT/2000(以及各種應用程序),甚至 Linux 上的 BSD(Berkeley Software Distribution)操作系統(FreeBSD、OpenBSD 等)。