QEMU架構淺析

1、QEMU簡介及與KVM等虛擬化的關係

QEMU是「Quick Emulator」的縮寫,是一個用C語言編寫的開源虛擬化軟件。本文的目的是描述本人所理解的QEMU技術架構的看法,並以此拋磚引玉。衆所周知,QEMU的源代碼開發文檔很是稀少,描述內部結構和工做機理的文檔更是百裏挑一,通常的開發人員想要從事QEMU的開發工做,一般只能從源代碼入手。所以,對於技術人員來講,瞭解QEMU是一項艱鉅的任務。編程

QEMU有幾種虛擬化模式。首先,它可使用基於內核的虛擬機(KVM)執行x86處理器硬件虛擬化,以幾乎比擬硬件本機的速度執行運算任務。其次,它能夠經過機器代碼的實時轉換來模擬其餘處理器以用於虛擬機運行不一樣平臺的操做系統。最後,它可使用實時轉換爲其餘架構運行簡單的程序,相似於Linux中的Wine。由於QEMU沒有圖形用戶界面(GUI),而其提供的核心能力又是關鍵而重要的,所以一般用做更復雜的虛擬化管理器的一部分。好比,咱們常用的開源VirtualBoxXen等虛擬化產品,其核心底層的虛擬化部分就有集成和使用QEMU,此外,主流的KVM虛擬化也是集成和使用QEMU的主力虛擬化管理器系統。緩存

KVM的角度來講,KVMKernel Virtual Machine)是Linux的一個內核驅動模塊,它可以讓Linux主機成爲一個Hypervisor(虛擬機監控器)。在支持VMXVirtual Machine Extension)功能的x86處理器中,Linux在原有的用戶模式和內核模式中新增長了客戶模式,而且客戶模式也擁有本身的內核模式和用戶模式,虛擬機就是運行在客戶模式中。KVM模塊的職責就是打開並初始化VMX功能,提供相應的接口以支持虛擬機的運行。KVM經過調用Linux自己內核功能,實現對CPU的底層虛擬化和內存的虛擬化,使Linux內核成爲虛擬化層。KVM20072月被導入Linux 2.6.20內核中。從存在形式來看,它包括兩個內核模塊:kvm.kokvm_intel.ko(或kvm_amd.ko),本質上,KVM是管理虛擬硬件設備的驅動,該驅動使用字符設備/dev/kvm(由KVM自己建立)做爲管理接口,主要負責vCPU的建立、虛擬內存的分配、vCPU寄存器的讀寫以及vCPU的運行。安全

QEMU的角度來講,QEMUQuick Emulator)自己並不包含或依賴KVM模塊,而是一套由Fabrice Bellard編寫的模擬計算機的自由軟件。QEMU虛擬機是一個純軟件的實現,能夠在沒有KVM模塊的狀況下獨立運行,可是性能比較低。QEMU有整套的虛擬機實現,包括處理器虛擬化、內存虛擬化以及I/O設備的虛擬化。在不須要KVM加速的狀況下,QEMU經過一個特殊的「重編譯器」對特定的處理器的二進制代碼進行翻譯,從而具備了跨平臺的通用性。QEMU有兩種工做模式:系統模式,能夠模擬出整個電腦系統,另外一種是用戶模式,能夠運行不一樣與當前硬件平臺的其餘平臺上的程序(好比在x86平臺上運行跑在ARM平臺上的程序)。目前最新版本是4.x。從QEMU角度來看,虛擬機運行期間,QEMU經過KVM模塊提供的系統調用接口進行內核設置,由KVM模塊負責將虛擬機置於處理器的VMX模式運行。QEMU使用了KVM模塊的虛擬化功能,爲本身的虛擬機提供硬件虛擬化加速以提升虛擬機的性能。網絡

而如今流行的KVM虛擬化平臺,就是在修改了QEMU代碼,把他模擬CPU、內存的代碼換成KVM,而網卡、顯示器等留着,所以QEMU+KVM就成了一個完整的虛擬化平臺。因爲KVM運行在內核空間,只是內核模塊,QEMU運行在用戶空間,實際模擬建立,管理各類虛擬硬件(磁盤,網卡,顯卡等)。從KVM的角度來講,用戶無法直接跟內核模塊交互,須要藉助用戶空間的管理工具,所以須要藉助QEMU這個運行在用戶空間的工具。KVMQEMU相輔相成,QEMU經過KVM達到了硬件虛擬化的速度,而KVM則經過QEMU來模擬設備並實現和內核空間的KVM的交互,雖然這個交互並不只僅只有QEMU可以辦到。此外,因爲QEMU模擬IO設備效率不高的緣由,如今經常採用半虛擬化的virtio方式來虛擬IO設備。架構

綜上,理解了QEMUKVM的關係,也就理解了VirtualBoxXen等虛擬化產品集成和使用QEMU的關係了。ide

2、QEMU架構及組成

QEMU的架構以下圖所示,由幾個基本的組件組成:工具

image.png

QEMU架構圖性能

如圖所示,QEMU由如下幾個部分組成:測試

l  Hypervisor控制仿真ui

l  Tiny Code GeneratorTCG)在虛擬機器代碼和宿主機代碼之間進行轉換。

l  軟件內存管理單元(MMU)處理內存訪問。

l  磁盤子系統處理不一樣的磁盤映像格式

l  設備子系統處理網卡和其餘硬件設備

下面將對這些組件介紹。

2.1 Hypervisor管理程序

Hypervisor(虛擬機管理程序)是一種建立和運行虛擬機的虛擬機監視器。 QEMU中的Hypervisor(虛擬機管理程序)從磁盤映像加載二進制機器代碼,使用TCG將其轉換爲本機機器代碼,鏈接到虛擬或實際設備,並啓動軟件MMU,而後開始在磁盤映像中模擬操做系統。其中,TCG和軟件MMU是實現虛擬化CPU和內存的關鍵。

而集成KVM後,QEMU將使用Linux內核的KVM功能以純模式執行虛擬機。KVM基本上是Linux內核中的Hypervisor(虛擬機管理程序)。它能夠並行運行多個操做系統。QEMU能夠在KVM中啓動一個新線程以執行模擬操做系統,而後KVM控制執行。從這部分來講,KVMHypervisor(虛擬機管理程序)替換掉了QEMUHypervisor(虛擬機管理程序)。

3.2微代碼生成器(TCG

QEMU中,Tiny Code GeneratorTCG)將源處理器機器代碼轉換爲虛擬機運行所需的機器代碼塊(如x86機器代碼塊)。從物理硬件的架構和角度上來講,不可能在一個處理器上運行爲另外一個處理器的指令集架構(ISA)編譯的機器代碼,例如,x86處理器上的ARM機器代碼。所以,引入中間環節對不一樣的處理器指令集架構(ISA)進行翻譯和轉換是實現虛擬化通用性的技術途徑和解決方案。在Tiny Code GeneratorTCG)中,這些已經翻譯的代碼塊放在轉換緩存中,並經過跳轉指令將源處理器的指令集(ISA)和目標處理器的指令集(ISA)連接在一塊兒。當Hypervisor(虛擬機管理程序)在執行代碼時,存放於轉換緩存中的連接指令能夠跳轉到指定的代碼塊,而且執行能夠在不一樣的已翻譯代碼塊上運行,直到須要翻譯新塊爲止。在執行的過程當中,若是遇到了須要翻譯的代碼塊,執行動做就會暫停並回會跳回到Hypervisor(虛擬機管理程序),Hypervisor(虛擬機管理程序)就會使用和協調TCG對須要進行二進制翻譯的源處理器指令集(ISA)進行轉換和翻譯並存儲到轉換緩存中。

下圖顯示了QEMUTCG工做原理:

image.png

.微代碼生成器工做原理

TCG在運行的過程當中存在一個小缺點,即它沒法正確運行自修改代碼,由於它沒有將修改後的代碼頁進行標記,再次運行時須要從新翻譯。這影響了QEMU的二進制運行效率,從另一個角度來講,這也增長了必定的安全性。自修改代碼在軟件世界中容易被漏洞利用。特別是緩衝區溢出攻&擊等內存損壞漏洞,這些漏洞利用威脅代理(例如後門)提供的特殊代碼覆蓋易受攻&擊的應用程序代碼,若是已經被覆蓋的代碼已經被運行(並所以被緩存),出了正常運行的會致使漏洞攻&擊利用外,更多的時候則會致使TCG運行和翻譯失敗,從而致使程序復現異常或崩潰。

此外,在翻譯的過程當中,若是新處理器使用的寄存器多於x86處理器而且具備許多複雜指令,那麼對TCG進行編程以處理和適應新的CPU仿真就可能須要大量的工做。目前來講,QEMU所支持的大部分處理器都擁有部分相同的指令集。例如,「MOV」指令幾乎存在於全部處理器中,而且能夠簡單地複製,除非CPU寄存器中存在一些位大小差別。例如,在32位處理器上模擬64位處理器可能須要許多額外的指令,這也須要更多時間在TCG轉換器中進行編程。

QEMU的源代碼中,有一個名爲'tcg'的子目錄,其中包含將機器指令轉換爲相應的x86機器指令的代碼。此代碼是一個用C編寫的簡單翻譯狀態機。還有用於內存訪問和跳轉的特殊轉換,由於它們能夠生成對軟件內存管理單元的調用。而虛擬化CPU和內存也每每是在一塊兒的,由於從本質上來講,CPU的工做就是對內存的區域數據進行搬運,CPU是內存的搬運工。在QEMU保護代碼塊以外的其餘內存區域。機器代碼中的跳轉和分支也必須到達正確的存儲器地址。

因此經過二進制翻譯技術,針對CPU的仿真和虛擬化就很是簡單了。TCGHypervisor(虛擬機管理程序)可以實現基於CPU的仿真,其中,其CPU仿真流程以下圖所示:

image.png

從上圖咱們能夠看到,針對CPU的仿真和虛擬化其實就是將源處理器的指令集(ISA)轉換和翻譯成目標處理器的指令集(ISA)。CPU仿真和虛擬化就是經過中間的轉換和翻譯來實現的,由此,針對CPU的虛擬化的第一種技術就徹底實現了。這種二進制翻譯技術是最先的CPU虛擬化技術,誕生了VMware這樣的虛擬化巨頭,也誕生了QEMU這樣的開源虛擬化鼻祖。

 

2.3硬件設備

虛擬機的硬件設備要求能夠經過直接鏈接主機中的實際物理設備或經過QEMU中的硬件設備仿真來實現。與硬件相關的大多數QEMU代碼位於目錄「hw」中。

QEMU中,存在兩種使用硬件設備的方式:直通模式使用主機實際物理設備和QEMU的設備驅動仿真實現的模擬虛擬設備。若是採用直通方式使用實際的物理設備,那麼就會搶佔主機的設備使用權,而且其餘虛擬機也將沒法使用該物理設備。在直通模式中,虛擬機能夠直接訪問USB總線或PCI總線,並能夠直接與設備通訊。通常狀況下,採用直通模式的物理設備都是很難進行QEMU仿真的設備,好比網絡攝像頭、串行和並行端口等。其餘設備由於大部分虛擬機都會使用,並且很難與主機共享,例如網絡設備,所以大都會使用QEMU模擬仿真的虛擬設備。好比在虛擬機的網絡設備中,可經過模擬網卡來解決,從而在網絡堆棧上添加額外的層。此外,QEMU能夠選擇鏈接到Linux內核中的「virtio」半虛擬化驅動程序,這意味着Linux內核處理虛擬機和硬件設備之間的輸入/輸出,而不採用QEMU的模擬設備進行中轉和傳輸(僅用做中介)。

 

2.4磁盤映像

QEMU能夠處理幾種不一樣的磁盤映像格式。首選格式爲rawqcow2Raw是一種很是簡單的格式,它將文件系統中的字節逐字節存儲在文件中。大多數其餘仿真器都支持此格式。Qcow2QEMU本身的圖像格式,對小圖像頗有用。而且支持磁盤映像壓縮以及捕獲磁盤映像狀態的快照。還支持另外兩種格式:在VirtualBox中使用的vdi和在VMWare中使用的vmdk

QEMU的磁盤映像經過其存儲IO協議棧來進行支持,其存儲協議棧以下圖所示:

image.png

image.png

QEMU存儲協議棧

從QEMU的存儲協議棧來講,應用程序和虛擬機內核的工做相似於裸機。虛擬機經過仿真硬件與QEMU交互,並將IO執行狀況的控制流和數據流交互給QEMUQEMU表明虛擬機對磁盤鏡像文件執行I / O操做。而從主機內核層面上,主機內核會將虛擬機I / O視爲一種用戶空間的應用程序IO請求進行正常的執行處理。

2.5軟件MMU

傳統處理器中的內存管理單元(MMU)處理對計算機內存位置的訪問。當處理器想要訪問某個存儲器地址時,MMU獲取該地址的內容。此內容能夠來自處理器芯片上的本地快速緩存,來自隨機存取存儲器(RAM)或來自光盤。它甚至能夠作出一些關於緩存某些內存位置的控制決定。

QEMU有一個基於軟件的MMU,其工做方式與硬件MMU相似。它使用地址轉換緩存,其中包含訪客地址、主機地址和偏移值,以提升轉換速度。它還容許智能連接代碼塊,以便在沒有內存故障的狀況下實現更快的執行,其中必須從新加載和從新轉換內存塊。

在尋找在QEMU中運行的虛擬機的漏洞時,軟件MMU是否正在進行翻譯和正確放置塊會是其測試和Fuzz的重點。

3、總結

其實搞清楚QEMU的技術架構和實現細節,咱們須要弄明白QEMU的架構和組成,以及每一個組件的做用及運行機制。此外,咱們還須要瞭解每一個組成組件之間的相互交互關係,從數據流的角度來看,其主要是控制流和數據流;從IO角度來看,其主要是網絡IO和存儲IO,從技術實現機制來看,其主要是虛擬化CPU和內存以及存儲、網絡協議棧的實現。本文有許多的未盡事宜,待請後續補充。

相關文章
相關標籤/搜索