快速上手QEMU:創(chuàng)建你的第一個虛擬機實例
在計算機技術的廣闊天地中,虛擬化技術無疑是一顆璀璨的明星,為我們的計算環(huán)境帶來了前所未有的靈活性和效率。而在虛擬化的眾多工具和技術中,Qemu 虛擬機管理器以其獨特的魅力和強大的功能,吸引著無數(shù)技術愛好者和專業(yè)人士的目光;Qemu,全稱 Quick Emulator,是一款開源的虛擬機監(jiān)視器。它誕生于 2003 年,由 Fabrice Bellard 發(fā)起開發(fā) ,最初的目標是提供一個通用的模擬器和虛擬化工具。經(jīng)過多年的發(fā)展和開源社區(qū)的積極貢獻,Qemu 已經(jīng)從一個簡單的項目,成長為一款功能強大且備受歡迎的虛擬機軟件,被廣泛應用于開發(fā)、測試、實驗以及云計算等眾多領域。
從本質上講,Qemu是一種高效的硬件模擬器,它能夠在軟件中模擬完整的機器,包括各種硬件設備,如CPU、內(nèi)存、硬盤、網(wǎng)卡等 。這意味著,通過Qemu,我們可以在一臺物理計算機上創(chuàng)建多個虛擬的計算機環(huán)境,每個環(huán)境都可以運行不同的操作系統(tǒng)和應用程序,就像它們運行在真實的物理機器上一樣。
而且,Qemu 支持多種處理器架構的模擬和虛擬化,如 x86、ARM、PowerPC、SPARC 等 。這種跨架構的模擬能力,使得 Qemu 在不同的硬件平臺和應用場景中都能發(fā)揮重要作用,無論是進行 x86 架構的服務器虛擬化,還是進行 ARM 架構的嵌入式系統(tǒng)開發(fā),Qemu 都能提供有力的支持。
一、Qemu簡介
1.1 Qemu概述
Qemu 是一款開源的硬件模擬器和虛擬機監(jiān)控器,其全稱為 Quick Emulator,即快速模擬器 。它允許用戶在一臺物理計算機上創(chuàng)建和運行多個虛擬機,每個虛擬機都可以運行不同的操作系統(tǒng),就像它們在獨立的物理計算機上運行一樣。Qemu 的特別之處在于,它不僅能夠模擬常見的 x86 架構,還對 ARM、PowerPC、MIPS、RISC-V 等多種硬件架構提供了出色的支持。
這使得開發(fā)者可以在 x86 架構的主機上,輕松模擬運行 ARM 架構的操作系統(tǒng)和應用程序,為跨平臺開發(fā)和測試提供了極大的便利。例如,在開發(fā)基于 ARM 架構的嵌入式系統(tǒng)時,開發(fā)者可以利用 Qemu 在普通的 PC 上搭建模擬環(huán)境,進行代碼編寫、調試和測試,大大降低了開發(fā)成本和時間。
從功能實現(xiàn)角度來看,Qemu 通過軟件的方式模擬硬件設備的行為。當虛擬機中的操作系統(tǒng)執(zhí)行指令時,Qemu 會將這些指令轉換為宿主機能夠理解的指令并執(zhí)行,同時模擬硬件設備的響應,使得虛擬機中的操作系統(tǒng)感覺像是在真實的硬件上運行。這種模擬機制使得 Qemu 具有極高的通用性和靈活性,幾乎可以運行任何操作系統(tǒng)和應用程序。
用戶可以通過不同Linux發(fā)行版所帶有的軟件包管理器來安裝QEMU。如在Debian系列的發(fā)行版上可以使用下面的命令來安裝:
sudo apt-get install qemu除此之外,也可以選擇從源碼安裝。
1.2Qemu源碼安裝流程
(1)獲取QEMU源碼,可以從QEMU下載官網(wǎng)上下載QEMU源碼的tar包,以命令行下載2.0版本的QEMU為例:
$wget http://wiki.qemu-project.org/download/qemu-2.0.0.tar.bz2
$tar xjvf qemu-2.0.0.tar.bz2(2)編譯及安裝,獲取源碼后,可以根據(jù)需求來配置和編譯QEMU:
$cd qemu-2.0.0 //如果使用的是git下載的源碼,執(zhí)行cd qemu
$./configure --enable-kvm --enable-debug --enable-vnc --enable-werror --target-list="x86_64-softmmu"
或者用戶模式(使能TCI)$./configure --target-list=arm-linux-user --enable-tcg-interpreter
$make -j8
$sudo make installconfigure腳本用于生成Makefile,其選項可以用./configure --help查看。這里使用到的選項含義如下:
--enable-kvm:編譯KVM模塊,使QEMU可以利用KVM來訪問硬件提供的虛擬化服務。
--enable-vnc:啟用VNC。
--enalbe-werror:編譯時,將所有的警告當作錯誤處理。
--target-list:選擇目標機器的架構。默認是將所有的架構都編譯,但為了更快的完成編譯,指定需要的架構即可。安裝好之后,會生成如下應用程序:
圖片
- ivshmem-client/server:這是一個 guest 和 host 共享內(nèi)存的應用程序,遵循 C/S 的架構。
- qemu-ga:這是一個不利用網(wǎng)絡實現(xiàn) guest 和 host 之間交互的應用程序(使用 virtio-serial),運行在 guest 中。
- qemu-io:這是一個執(zhí)行 Qemu I/O 操作的命令行工具。
- qemu-system-x86_64:Qemu 的核心應用程序,虛擬機就由它創(chuàng)建的。
- qemu-img:創(chuàng)建虛擬機鏡像文件的工具,下面有例子說明。
- qemu-nbd:磁盤掛載工具。
1.3常用命令與操作示例
⑴創(chuàng)建虛擬機磁盤鏡像:在使用 Qemu 創(chuàng)建虛擬機之前,需要先創(chuàng)建一個虛擬磁盤鏡像,用于存儲虛擬機的操作系統(tǒng)和數(shù)據(jù) ??梢允褂胵emu-img工具來創(chuàng)建磁盤鏡像 。例如,要創(chuàng)建一個大小為 20GB,格式為 qcow2 的磁盤鏡像文件 “myvm.qcow2”,可以在命令行中輸入以下命令:
qemu-img create -f qcow2 myvm.qcow2 20G其中,-f參數(shù)指定磁盤鏡像的格式,qcow2是一種常用的磁盤鏡像格式,具有寫時復制等特性,可以有效節(jié)省磁盤空間 。myvm.qcow2是磁盤鏡像文件的名稱,20G表示磁盤鏡像的大小為 20GB 。
⑵啟動虛擬機:創(chuàng)建好磁盤鏡像后,就可以使用qemu-system-x86_64命令來啟動虛擬機 。假設要啟動剛才創(chuàng)建的虛擬機,并指定內(nèi)存大小為 2GB,使用 Windows 10 的 ISO 鏡像文件進行安裝,可以使用以下命令:
qemu-system-x86_64 -m 2048 -cdrom /path/to/windows10.iso -drive file=myvm.qcow2,format=qcow2其中,-m參數(shù)指定虛擬機的內(nèi)存大小,單位為 MB,這里設置為 2048MB,即 2GB 。-cdrom參數(shù)指定用于安裝操作系統(tǒng)的 ISO 鏡像文件的路徑,/path/to/windows10.iso需要替換為實際的 Windows 10 ISO 鏡像文件的路徑 。-drive參數(shù)用于指定虛擬機的磁盤驅動器,file=myvm.qcow2指定使用前面創(chuàng)建的磁盤鏡像文件,format=qcow2指定磁盤鏡像的格式為 qcow2 。執(zhí)行該命令后,會彈出一個窗口,顯示虛擬機的啟動界面,用戶可以按照提示進行操作系統(tǒng)的安裝 。
⑶管理虛擬機:在虛擬機運行過程中,可以使用一些命令來管理虛擬機 。例如,要暫停虛擬機的運行,可以在 Qemu 的控制臺中按下Ctrl + Alt + 2組合鍵,進入 Qemu 的監(jiān)視器模式,然后輸入stop命令 。要恢復虛擬機的運行,在監(jiān)視器模式下輸入cont命令即可 。如果要關閉虛擬機,可以在監(jiān)視器模式下輸入system_powerdown命令 。
此外,還可以使用savevm命令來保存虛擬機的當前狀態(tài),使用loadvm命令來加載保存的狀態(tài) 。例如,要保存虛擬機的當前狀態(tài)為 “snapshot1”,可以在監(jiān)視器模式下輸入savevm snapshot1命令;要加載名為 “snapshot1” 的狀態(tài),可以輸入loadvm snapshot1命令 。
1.4Qemu獨特功能
全系統(tǒng)仿真:Qemu 的全系統(tǒng)仿真功能堪稱一絕,它能夠模擬完整的計算機系統(tǒng),包括 CPU、內(nèi)存、存儲設備、網(wǎng)絡設備等 。這意味著用戶可以在 Qemu 中運行各種操作系統(tǒng),無論是 Windows、Linux、macOS,還是一些小眾的嵌入式操作系統(tǒng),都不在話下。例如,安全研究人員可以利用 Qemu 搭建一個包含特定操作系統(tǒng)和應用程序的模擬環(huán)境,用于進行漏洞挖掘和安全測試,不用擔心對真實系統(tǒng)造成損害。在開發(fā)操作系統(tǒng)時,開發(fā)者也可以借助 Qemu 的全系統(tǒng)仿真功能,在虛擬環(huán)境中進行開發(fā)和調試,方便快捷。
- 動態(tài)二進制翻譯:這是 Qemu 的核心技術之一,動態(tài)二進制翻譯技術允許 Qemu 在運行時將客戶機的指令集動態(tài)轉換為宿主機的指令集 。通過這種方式,Qemu 能夠在不同架構的宿主機上運行不同架構的客戶機操作系統(tǒng),實現(xiàn)了跨架構的虛擬化。例如,在 x86 架構的主機上運行 ARM 架構的操作系統(tǒng)時,Qemu 會將 ARM 指令動態(tài)翻譯成 x86 指令,讓程序能夠在 x86 主機上順利運行。這種技術不僅提高了 Qemu 的兼容性,還在一定程度上提升了性能,因為它可以根據(jù)實際運行情況對指令進行優(yōu)化。
- 豐富的設備模擬:Qemu 提供了豐富的設備模擬功能,支持多種常見的硬件設備,如虛擬網(wǎng)卡、虛擬磁盤、虛擬顯卡、USB 設備等 。這些設備模擬使得虛擬機可以與外部環(huán)境進行交互,滿足各種應用場景的需求。比如,在進行網(wǎng)絡應用開發(fā)和測試時,用戶可以在 Qemu 虛擬機中模擬不同類型的網(wǎng)絡設備,測試應用程序在不同網(wǎng)絡環(huán)境下的性能和穩(wěn)定性。同時,Qemu 還支持對一些特殊設備的模擬,為特定領域的開發(fā)和研究提供了便利。
- 插件擴展功能:Qemu 具備良好的插件擴展機制,用戶可以通過編寫插件來擴展 Qemu 的功能 。這使得 Qemu 能夠適應各種復雜的應用場景和用戶需求。例如,一些開發(fā)者編寫了自定義的設備插件,用于模擬特定的硬件設備,滿足特定行業(yè)的開發(fā)和測試需求。還有一些插件用于優(yōu)化 Qemu 的性能、增強安全性或者提供新的管理功能,使得 Qemu 的功能不斷豐富和完善。
二、Qemu 的工作原理
QEMU作為系統(tǒng)模擬器時,會模擬出一臺能夠獨立運行操作系統(tǒng)的虛擬機。如下圖所示,每個虛擬機對應主機(Host)中的一個QEMU進程,而虛擬機的vCPU對應QEMU進程的一個線程。
系統(tǒng)虛擬化最主要是虛擬出CPU、內(nèi)存及I/O設備。虛擬出的CPU稱之為vCPU,QEMU為了提升效率,借用KVM、XEN等虛擬化技術,直接利用硬件對虛擬化的支持,在主機上安全地運行虛擬機代碼(需要硬件支持)。虛擬機vCPU調用KVM的接口來執(zhí)行任務的流程如下:
open("/dev/kvm")
ioctl(KVM_CREATE_VM)
ioctl(KVM_CREATE_VCPU)
for (;;) {
ioctl(KVM_RUN)
switch (exit_reason) {
case KVM_EXIT_IO: /* ... */
case KVM_EXIT_HLT: /* ... */
}
}QEMU發(fā)起ioctrl來調用KVM接口,KVM則利用硬件擴展直接將虛擬機代碼運行于主機之上,一旦vCPU需要操作設備寄存器,vCPU將會停止并退回到QEMU,QEMU去模擬出操作結果。
虛擬機內(nèi)存會被映射到QEMU的進程地址空間,在啟動時分配。在虛擬機看來,QEMU所分配的主機上的虛擬地址空間為虛擬機的物理地址空間。
QEMU在主機用戶態(tài)模擬虛擬機的硬件設備,vCPU對硬件的操作結果會在用戶態(tài)進行模擬,如虛擬機需要將數(shù)據(jù)寫入硬盤,實際結果是將數(shù)據(jù)寫入到了主機中的一個鏡像文件中。
2.1系統(tǒng)架構解讀
Qemu 的系統(tǒng)架構可以分為用戶態(tài)和內(nèi)核態(tài)兩大部分,這種分層設計使得 Qemu 能夠高效地實現(xiàn)硬件模擬和虛擬化功能,各部分組件相互協(xié)作,共同為虛擬機提供完整的運行環(huán)境。
在用戶態(tài),Qemu 包含了豐富的組件。用戶接口是用戶與 Qemu 交互的橋梁,用戶可以通過命令行、圖形界面或者 API 等方式,向 Qemu 發(fā)送各種指令,如創(chuàng)建虛擬機、啟動虛擬機、配置虛擬機參數(shù)等 。設備模型是用戶態(tài)的重要組成部分,它負責模擬各種硬件設備的行為。Qemu 通過設備模型模擬出虛擬的 CPU、內(nèi)存、硬盤、網(wǎng)卡、顯卡等設備,使得虛擬機中的操作系統(tǒng)能夠像在真實硬件上一樣訪問這些設備。以虛擬網(wǎng)卡為例,設備模型會模擬網(wǎng)卡的接收和發(fā)送數(shù)據(jù)的功能,當虛擬機中的操作系統(tǒng)發(fā)送網(wǎng)絡數(shù)據(jù)包時,設備模型會將這些數(shù)據(jù)包進行處理,并通過宿主機的網(wǎng)絡接口發(fā)送出去;反之,當宿主機接收到網(wǎng)絡數(shù)據(jù)包時,設備模型會將其轉發(fā)給虛擬機中的操作系統(tǒng)。
虛擬設備驅動程序也是用戶態(tài)的關鍵組件之一,它為虛擬機中的操作系統(tǒng)提供了訪問虛擬設備的接口。這些驅動程序模擬了真實設備驅動程序的功能,使得操作系統(tǒng)能夠正常識別和使用虛擬設備。例如,虛擬顯卡的驅動程序會模擬真實顯卡的功能,將虛擬機中的圖形數(shù)據(jù)進行處理和渲染,然后通過宿主機的顯示設備展示出來。
在內(nèi)核態(tài),Qemu 主要包含虛擬機監(jiān)控程序(VMM)和虛擬機管理器(VM Manager) 。VMM 是 Qemu 的核心組件之一,它負責管理虛擬機的運行狀態(tài),監(jiān)控虛擬機的指令執(zhí)行,實現(xiàn)硬件虛擬化的核心功能。VMM 通過與宿主機內(nèi)核的交互,實現(xiàn)對 CPU、內(nèi)存等硬件資源的虛擬化管理。例如,在處理 CPU 虛擬化時,VMM 會負責模擬目標架構的指令集、寄存器等關鍵組件,使得虛擬機能夠運行不同架構的操作系統(tǒng)。當虛擬機執(zhí)行指令時,VMM 會捕獲這些指令,并根據(jù)需要進行處理和轉換,然后將其發(fā)送給宿主機 CPU 執(zhí)行。
VM Manager 則主要負責虛擬機的創(chuàng)建、管理和調度。它根據(jù)用戶的請求,創(chuàng)建新的虛擬機,并為其分配必要的資源,如內(nèi)存、CPU 時間片等 。同時,VM Manager 還負責監(jiān)控虛擬機的運行狀態(tài),在多個虛擬機之間進行資源調度,確保每個虛擬機都能夠獲得合理的資源分配,從而保證整個系統(tǒng)的性能和穩(wěn)定性。當一個虛擬機需要更多的 CPU 時間片時,VM Manager 會根據(jù)預設的調度策略,調整各個虛擬機的 CPU 分配,使得系統(tǒng)資源得到合理利用。
用戶態(tài)和內(nèi)核態(tài)的組件之間通過特定的接口進行交互,以實現(xiàn)高效的協(xié)作。例如,用戶態(tài)的設備模型通過與內(nèi)核態(tài)的 VMM 進行交互,將虛擬機對硬件設備的訪問請求傳遞給 VMM,VMM 再根據(jù)請求進行相應的處理,并將結果返回給設備模型,設備模型最后將結果返回給虛擬機中的操作系統(tǒng) 。這種交互機制確保了虛擬機能夠在 Qemu 提供的模擬環(huán)境中正常運行,同時也保證了系統(tǒng)的性能和穩(wěn)定性。
2.2指令翻譯與虛擬化實現(xiàn)
(1)動態(tài)二進制翻譯技術:動態(tài)二進制翻譯是 Qemu 實現(xiàn)虛擬化的核心技術之一,它允許 Qemu 在運行時將客戶機的指令集動態(tài)轉換為宿主機的指令集 。簡單來說,當虛擬機中的操作系統(tǒng)執(zhí)行指令時,Qemu 會將這些指令實時翻譯成宿主機能夠理解和執(zhí)行的指令。例如,在 x86 架構的宿主機上運行 ARM 架構的虛擬機時,Qemu 會將 ARM 指令動態(tài)翻譯成 x86 指令,使得 ARM 架構的操作系統(tǒng)和應用程序能夠在 x86 主機上順利運行。
Qemu 使用了一種稱為 “Tiny Code Generator(TCG)” 的技術來實現(xiàn)動態(tài)二進制翻譯 。TCG 是一個輕量級的代碼生成器,它能夠將客戶機的指令動態(tài)地轉換為宿主機的指令,并生成高效的機器碼。具體過程如下:首先,Qemu 從虛擬機中讀取客戶機的指令,然后將這些指令翻譯成 TCG 中間表示形式(IR) 。TCG 中間表示是一種抽象的指令表示,它不依賴于具體的硬件架構,具有較高的通用性。接下來,TCG 會根據(jù)宿主機的架構,將中間表示進一步翻譯成宿主機的目標指令 。在翻譯過程中,TCG 會對指令進行優(yōu)化,以提高執(zhí)行效率。例如,它會合并一些可以合并的指令,減少指令的執(zhí)行次數(shù);還會根據(jù)宿主機的硬件特性,選擇最合適的指令序列來實現(xiàn)相同的功能。通過這種動態(tài)二進制翻譯技術,Qemu 能夠在不同架構的宿主機上運行各種不同架構的客戶機操作系統(tǒng),大大提高了虛擬化的靈活性和兼容性。
(2)中斷與模擬設備操作實現(xiàn)虛擬化:中斷是計算機系統(tǒng)中一種重要的機制,用于處理異步事件。在 Qemu 的虛擬化環(huán)境中,中斷的模擬和處理對于實現(xiàn)完整的虛擬化至關重要 。當虛擬機中的設備產(chǎn)生中斷請求時,Qemu 需要準確地模擬這個中斷過程,將中斷信號傳遞給虛擬機中的操作系統(tǒng),并確保操作系統(tǒng)能夠正確地響應和處理這個中斷。
以虛擬網(wǎng)卡為例,當宿主機接收到網(wǎng)絡數(shù)據(jù)包時,虛擬網(wǎng)卡設備模型會產(chǎn)生一個中斷請求,通知虛擬機中的操作系統(tǒng)有新的網(wǎng)絡數(shù)據(jù)到達 。Qemu 會捕獲這個中斷請求,并將其轉換為虛擬機能夠識別的中斷信號,然后傳遞給虛擬機中的操作系統(tǒng)。操作系統(tǒng)接收到中斷信號后,會調用相應的中斷處理程序,從虛擬網(wǎng)卡中讀取網(wǎng)絡數(shù)據(jù)包,并進行后續(xù)的處理。在這個過程中,Qemu 需要模擬中斷控制器的行為,確保中斷信號的正確傳遞和處理。
同時,Qemu 對設備的模擬操作也是實現(xiàn)虛擬化的關鍵。Qemu 通過軟件模擬各種硬件設備的功能和行為,使得虛擬機中的操作系統(tǒng)能夠像操作真實硬件設備一樣操作這些虛擬設備 。例如,在模擬硬盤設備時,Qemu 會模擬硬盤的讀寫操作。當虛擬機中的操作系統(tǒng)向虛擬硬盤寫入數(shù)據(jù)時,Qemu 會將數(shù)據(jù)存儲在宿主機的文件系統(tǒng)中,以模擬硬盤的存儲功能;當操作系統(tǒng)從虛擬硬盤讀取數(shù)據(jù)時,Qemu 會從宿主機的文件系統(tǒng)中讀取相應的數(shù)據(jù),并返回給操作系統(tǒng)。通過這種方式,Qemu 實現(xiàn)了對硬件設備的完整模擬,為虛擬機提供了一個與真實硬件環(huán)境相似的運行環(huán)境,使得各種操作系統(tǒng)和應用程序能夠在虛擬機中正常運行,實現(xiàn)了高效的硬件虛擬化。
2.3創(chuàng)建及使用虛擬機
使用qemu-img創(chuàng)建虛擬機鏡像,虛擬機鏡像用來模擬虛擬機的硬盤,在啟動虛擬機之前需要創(chuàng)建鏡像文件。
qemu-img create -f qcow2 test-vm-1.qcow2 10G-f 選項用于指定鏡像的格式,qcow2 格式是 Qemu 最常用的鏡像格式,采用來寫時復制技術來優(yōu)化性能。test-vm-1.qcow2 是鏡像文件的名字,10G是鏡像文件大小。鏡像文件創(chuàng)建完成后,可使用 qemu-system-x86 來啟動x86 架構的虛擬機:
使用 qemu-system-x86 來啟動 x86 架構的虛擬機
qemu-system-x86_64 test-vm-1.qcow2因為 test-vm-1.qcow2 中并未給虛擬機安裝操作系統(tǒng),所以會提示 “No bootable device”,無可啟動設備。
啟動 VM 安裝操作系統(tǒng)鏡像
qemu-system-x86_64 -m 2048 -enable-kvm test-vm-1.qcow2 -cdrom ./Centos-Desktop-x86_64-20-1.iso-m 指定虛擬機內(nèi)存大小,默認單位是 MB, -enable-kvm 使用 KVM 進行加速,-cdrom 添加 fedora 的安裝鏡像。可在彈出的窗口中操作虛擬機,安裝操作系統(tǒng),安裝完成后重起虛擬機便會從硬盤 ( test-vm-1.qcow2 ) 啟動。之后再啟動虛擬機只需要執(zhí)行:
qemu-system-x86_64 -m 2048 -enable-kvm test-vm-1.qcow2qemu-img 支持非常多種的文件格式,可以通過 qemu-img -h 查看,其中 raw 和 qcow2 是比較常用的兩種,raw 是 qemu-img 命令默認的,qcow2 是 qemu 目前推薦的鏡像格式,是功能最多的格式。
三、Qemu應用場景
3.1開發(fā)與測試領域
在軟件開發(fā)過程中,開發(fā)人員常常需要在不同的操作系統(tǒng)和硬件平臺上對軟件進行測試,以確保軟件的兼容性和穩(wěn)定性 。Qemu 提供了一個理想的測試環(huán)境,它可以模擬多種硬件架構和操作系統(tǒng),讓開發(fā)人員在一臺物理計算機上就能完成對軟件在不同環(huán)境下的測試工作。例如,開發(fā)一款跨平臺的應用程序時,開發(fā)人員可以利用 Qemu 創(chuàng)建 Windows、Linux、macOS 等多種操作系統(tǒng)的虛擬機,在這些虛擬機中分別運行應用程序,測試其在不同系統(tǒng)下的功能完整性、界面顯示、性能表現(xiàn)等 。這樣可以提前發(fā)現(xiàn)并解決軟件在不同平臺上可能出現(xiàn)的兼容性問題,大大提高軟件的質量和可靠性。
對于硬件開發(fā),Qemu 同樣發(fā)揮著重要作用。在硬件設計階段,工程師可以使用 Qemu 模擬目標硬件平臺,進行硬件相關軟件的開發(fā)和調試 。比如,開發(fā)一款基于 ARM 架構的嵌入式系統(tǒng)時,在實際硬件還未生產(chǎn)出來之前,工程師就可以利用 Qemu 模擬 ARM 硬件環(huán)境,編寫和調試驅動程序、操作系統(tǒng)內(nèi)核等軟件部分。通過在 Qemu 模擬環(huán)境中進行充分的測試和優(yōu)化,可以減少硬件開發(fā)過程中的錯誤和風險,縮短硬件開發(fā)周期,降低開發(fā)成本 。而且,Qemu 支持對硬件設備的詳細模擬,工程師可以模擬各種硬件故障和異常情況,測試軟件在這些情況下的應對能力,提高硬件系統(tǒng)的穩(wěn)定性和可靠性。
3.2云計算與數(shù)據(jù)中心
在云計算和數(shù)據(jù)中心領域,Qemu 是實現(xiàn)資源虛擬化的關鍵技術之一 。它與 KVM(Kernel-based Virtual Machine)相結合,為云計算提供了強大的支持。KVM 是 Linux 內(nèi)核中的一個模塊,它利用硬件虛擬化擴展(如 Intel VT 或 AMD-V)來實現(xiàn)高效的虛擬化 。
Qemu 則作為 KVM 的用戶空間工具,負責模擬硬件設備,為虛擬機提供完整的運行環(huán)境。通過這種組合,云計算提供商可以在一臺物理服務器上創(chuàng)建多個虛擬機,將服務器的計算、存儲和網(wǎng)絡資源進行虛擬化分割,為不同的用戶提供獨立的虛擬機服務 。
這種虛擬化技術在云計算和數(shù)據(jù)中心中有諸多優(yōu)勢。首先,它提高了服務器的資源利用率。傳統(tǒng)的數(shù)據(jù)中心中,服務器的資源往往不能得到充分利用,很多服務器在大部分時間內(nèi)處于低負載運行狀態(tài) 。通過虛擬化技術,多個虛擬機可以共享一臺物理服務器的資源,根據(jù)實際需求動態(tài)分配資源,大大提高了服務器的利用率,降低了硬件成本和能源消耗 。
其次,虛擬化技術增強了系統(tǒng)的靈活性和可擴展性。云計算提供商可以根據(jù)用戶的需求,快速創(chuàng)建、刪除或調整虛擬機的配置,實現(xiàn)資源的動態(tài)分配和回收 。用戶也可以根據(jù)自己的業(yè)務需求,靈活選擇虛擬機的規(guī)格和配置,無需擔心硬件資源的限制。此外,Qemu和KVM的結合還提供了良好的隔離性和安全性,每個虛擬機都運行在獨立的隔離環(huán)境中,相互之間不會干擾,保證了用戶數(shù)據(jù)的安全和隱私 。
3.3教育與科研用途
在教育領域,Qemu 為學生和教師提供了一個便捷的實驗環(huán)境 。在計算機相關課程的教學中,學生常常需要實踐操作不同的操作系統(tǒng)和硬件環(huán)境,但由于實際硬件設備的限制,很難為每個學生提供多樣化的實驗環(huán)境 。Qemu 的出現(xiàn)解決了這個問題,教師可以利用 Qemu 創(chuàng)建多個虛擬機,每個虛擬機運行不同的操作系統(tǒng)和實驗軟件,學生可以在虛擬機中進行各種實驗操作,如操作系統(tǒng)安裝、配置,網(wǎng)絡實驗,軟件開發(fā)等 。這樣不僅提高了教學效果,還能讓學生在實踐中更好地理解計算機系統(tǒng)的原理和機制。
在科研方面,Qemu 也有著廣泛的應用 。科研人員在進行計算機體系結構、操作系統(tǒng)、網(wǎng)絡協(xié)議等領域的研究時,常常需要搭建復雜的實驗環(huán)境 。Qemu 可以模擬各種硬件平臺和操作系統(tǒng),為科研人員提供了一個靈活、可定制的實驗平臺 。例如,在研究新型的計算機體系結構時,科研人員可以利用 Qemu 模擬新的處理器架構和硬件設備,驗證設計的可行性和性能優(yōu)勢 。
在研究操作系統(tǒng)的性能優(yōu)化和安全機制時,科研人員可以在 Qemu 虛擬機中運行不同版本的操作系統(tǒng),進行各種性能測試和安全實驗 。Qemu 還支持對網(wǎng)絡設備和網(wǎng)絡協(xié)議的模擬,方便科研人員進行網(wǎng)絡相關的研究和實驗,推動科研工作的順利開展。
四、Qemu源碼結構
Qemu軟件虛擬化實現(xiàn)的思路是采用二進制指令翻譯技術,主要是提取 guest 代碼,然后將其翻譯成 TCG 中間代碼,最后再將中間代碼翻譯成 host 指定架構的代碼,如 x86 體系就翻譯成其支持的代碼形式,ARM 架構同理。
圖片
所以,從宏觀上看,源碼結構主要包含以下幾個部分:
- /vl.c:最主要的模擬循環(huán),虛擬機環(huán)境初始化,和 CPU 的執(zhí)行。
- /target-arch/translate.c:將 guest 代碼翻譯成不同架構的 TCG 操作碼。
- /tcg/tcg.c:主要的 TCG 代碼。
- /tcg/arch/tcg-target.c:將 TCG 代碼轉化生成主機代碼。
- /cpu-exec.c:主要尋找下一個二進制翻譯代碼塊,如果沒有找到就請求得到下一個代碼塊,并且操作生成的代碼塊。
其中,涉及的主要幾個函數(shù)如下:
圖片
知道了這個總體的代碼結構,再去具體了解每一個模塊可能會相對容易一點。
(1)開始執(zhí)行
主要比較重要的c文件有:/vl.c,/cpus.c, /exec-all.c, /exec.c, /cpu-exec.c。
QEMU的main函數(shù)定義在/vl.c中,它也是執(zhí)行的起點,這個函數(shù)的功能主要是建立一個虛擬的硬件環(huán)境。它通過參數(shù)的解析,將初始化內(nèi)存,需要的模擬的設備初始化,CPU參數(shù),初始化KVM等等。接著程序就跳轉到其他的執(zhí)行分支文件如:/cpus.c, /exec-all.c, /exec.c, /cpu-exec.c。
(2)硬件模擬
所有的硬件設備都在/hw/ 目錄下面,所有的設備都有獨自的文件,包括總線,串口,網(wǎng)卡,鼠標等等。它們通過設備模塊串在一起,在vl.c中的machine _init中初始化。這里就不講每種設備是怎么實現(xiàn)的了。
(3)目標機器
現(xiàn)在QEMU模擬的CPU架構有:Alpha, ARM, Cris, i386, M68K, PPC, Sparc, Mips, MicroBlaze, S390X and SH4。
我們在QEMU中使用./configure 可以配置運行的架構,這個腳本會自動讀取本機真實機器的CPU架構,并且編譯的時候就編譯對應架構的代碼。對于不同的QEMU做的事情都不同,所以不同架 構下的代碼在不同的目錄下面。/target-arch/目錄就對應了相應架構的代碼,如/target-i386/就對應了x86系列的代碼部分。雖然 不同架構做法不同,但是都是為了實現(xiàn)將對應客戶機CPU架構的TBs轉化成TCG的中間代碼。這個就是TCG的前半部分。
(4)主機
這個部分就是使用TCG代碼生成主機的代碼,這部分代碼在/tcg/里面,在這個目錄里面也對應了不同的架構,分別在不同的子目錄里面,如i386就在/tcg/i386中。整個生成主機代碼的過程也可以教TCG的后半部分。
(5)文件總結
/vl.c: 最主要的模擬循環(huán),虛擬機機器環(huán)境初始化,和CPU的執(zhí)行。
/target-arch/translate.c 將客戶機代碼轉化成不同架構的TCG操作碼。
/tcg/tcg.c 主要的TCG代碼。
/tcg/arch/tcg-target.c 將TCG代碼轉化生成主機代碼
/cpu-exec.c 其中的cpu-exec()函數(shù)主要尋找下一個TB(翻譯代碼塊),如果沒找到就請求得到下一個TB,并且操作生成的代碼塊。4.1TCG動態(tài)翻譯
QEMU在 0.9.1版本之前使用DynGen翻譯c代碼.當我們需要的時候TCG會動態(tài)的轉變代碼,這個想法的目的是用更多的時間去執(zhí)行我們生成的代碼。當新的代 碼從TB中生成以后, 將會被保存到一個cache中,因為很多相同的TB會被反復的進行操作,所以這樣類似于內(nèi)存的cache,能夠提高使用效率。而 cache的刷新使用LRU算法。
圖片
編譯器在執(zhí)行器會從源代碼中產(chǎn)生目標代碼,像GCC這種編譯器,它為了產(chǎn)生像函數(shù)調用目標代碼會產(chǎn)生一些特殊的匯編目標代碼,他們能夠讓編譯器需要知道在調用函數(shù)。需要什么,以及函數(shù)調用以后需要返回什么,這些特殊的匯編代碼產(chǎn)生過程就叫做函數(shù)的Prologue和Epilogue,這里就叫前端和后段吧。我在其他文章中也分析過匯編調用函數(shù)的過程,至于匯編里面函數(shù)調用過程中寄存器是如何變化的,在本文中就不再描述了。
函數(shù)的后端會恢復前端的狀態(tài),主要做下面2點:
- 恢復堆棧的指針,包括棧頂和基地址。
- 修改cs和ip,程序回到之前的前端記錄點。
TCG就如編譯器一樣可以產(chǎn)生目標代碼,代碼會保存在緩沖區(qū)中,當進入前端和后端的時候就會將TCG生成的緩沖代碼插入到目標代碼中。
接下來我們就來看下如何翻譯代碼的:
①客戶機代碼
圖片
②TCG中間代碼
圖片
③主機代碼
圖片
4.2TB鏈
在QEMU中,從代碼cache到靜態(tài)代碼再回到代碼cache,這個過程比較耗時,所以在QEMU中涉及了一個TB鏈將所有TB連在一起,可以讓一個TB執(zhí)行完以后直接跳到下一個TB,而不用每次都返回到靜態(tài)代碼部分。具體過程如下圖:
圖片
4.3TCG代碼分析
接下來來看看QEMU代碼中中到底怎么來執(zhí)行這個TCG的,看看它是如何生成主機代碼的。
main_loop(...){/vl.c} :
函數(shù)main_loop 初始化qemu_main_loop_start()然后進入無限循環(huán)cpu_exec_all() , 這個是QEMU的一個主要循環(huán),在里面會不斷的判斷一些條件,如虛擬機的關機斷電之類的。
qemu_main_loop_start(...){/cpus.c} :
函數(shù)設置系統(tǒng)變量 qemu_system_ready = 1并且重啟所有的線程并且等待一個條件變量。
cpu_exec_all(...){/cpus.c} :
它是cpu循環(huán),QEMU能夠啟動256個cpu核,但是這些核將會分時運行,然后執(zhí)行qemu_cpu_exec() 。
struct CPUState{/target-xyz/cpu.h} :
它是CPU狀態(tài)結構體,關于cpu的各種狀態(tài),不同架構下面還有不同。cpu_exec(...){/cpu-exec.c}:
這個函數(shù)是主要的執(zhí)行循環(huán),這里第一次翻譯之前說道德TB,TB被初始化為(TranslationBlock *tb) ,然后不停的執(zhí)行異常處理。其中嵌套了兩個無限循環(huán) find tb_find_fast() 和tcg_qemu_tb_exec();cantb_find_fast()為客戶機初始化查詢下一個TB,并且生成主機代碼。tcg_qemu_tb_exec()執(zhí)行生成的主機代碼
struct TranslationBlock {/exec-all.h}:
結構體TranslationBlock包含下面的成員:PC, CS_BASE, Flags (表明TB), tc_ptr (指向這個TB翻譯代碼的指針), tb_next_offset[2], tb_jmp_offset[2] (接下去的Tb), *jmp_next[2], *jmp_first (之前的TB).tb_find_fast(...){/cpu-exec.c} :
函數(shù)通過調用獲得程序指針計數(shù)器,然后傳到一個哈希函數(shù)從 tb_jmp_cache[] (一個哈希表)得到TB的所以,所以使用tb_jmp_cache可以找到下一個TB。如果沒有找到下一個TB,則使用tb_find_slow。
tb_find_slow(...){/cpu-exec.c}:
這個是在快速查找失敗以后試圖去訪問物理內(nèi)存,尋找TB。
tb_gen_code(...){/exec.c}:
開始分配一個新的TB,TB的PC是剛剛從CPUstate里面通過using get_page_addr_code()找到的phys_pc = get_page_addr_code(env, pc);tb = tb_alloc(pc);ph當調用cpu_gen_code() 以后,接著會調用tb_link_page(),它將增加一個新的TB,并且指向它的物理頁表。
cpu_gen_code(...){translate-all.c}:
函數(shù)初始化真正的代碼生成,在這個函數(shù)里面有下面的函數(shù)調用:
gen_intermediate_code(){
/target-arch/translate.c}->gen_intermediate_code_internal(){
/target-arch/translate.c }->disas_insn(){/target-arch/translate.c}disas_insn(){/target-arch/translate.c}:
函數(shù)disas_insn() 真正的實現(xiàn)將客戶機代碼翻譯成TCG代碼,它通過一長串的switch case,將不同的指令做不同的翻譯,最后調用tcg_gen_code。tcg_gen_code(...){/tcg/tcg.c}:
這個函數(shù)將TCG的代碼轉化成主機代碼,這個就不細細說明了,和前面類似。#define tcg_qemu_tb_exec(...){/tcg/tcg.g}:通過上面的步驟,當TB生成以后就通過這個函數(shù)進行執(zhí)行
next_tb = tcg_qemu_tb_exec(tc_ptr) :
extern uint8_t code_gen_prologue[];
#define tcg_qemu_tb_exec(tb_ptr) ((long REGPARM(*)(void *)) code_gen_prologue)(tb_ptr)通過上面的步驟我們就解析了QEMU是如何將客戶機代碼翻譯成主機代碼的,了解了TCG的工作原理。接下來看看QEMU與KVM是怎么聯(lián)系的。
4.4IOCTL使用流程
在QEMU-KVM中,用戶空間的QEMU是通過IOCTL與內(nèi)核空間的KVM模塊進行通訊的。
(1)創(chuàng)建KVM
在/vl.c中通過kvm_init()將會創(chuàng)建各種KVM的結構體變量,并且通過IOCTL與已經(jīng)初始化好的KVM模塊進行通訊,創(chuàng)建虛擬機。然后創(chuàng)建VCPU,等等。
(2)KVM_RUN
這個IOCTL是使用最頻繁的,整個KVM運行就不停在執(zhí)行這個IOCTL,當KVM需要QEMU處理一些指令和IO等等的時候就會退出通過這個IOCTL退回到QEMU進行處理,不然就會一直在KVM中執(zhí)行。
它的初始化過程:
vl.c中調用machine->init初始化硬件設備接著調用pc_init_pci,然后再調用pc_init1;接著通過下面的調用初始化KVM的主循環(huán),以及CPU循環(huán)。在CPU循環(huán)的過程中不斷的執(zhí)行KVM_RUN與KVM進行交互。
pc_init1->pc_cpus_init->pc_new_cpu->cpu_x86_init->qemu_init_vcpu->kvm_init_vcpu->ap_main_loop->kvm_main_loop_cpu->kvm_cpu_exec->kvm_run(3)KVM_IRQ_LINE
這個IOCTL和KVM_RUN是不同步的,它也是個頻率非常高的調用,它就是一般中斷設備的中斷注入入口。當設備有中斷就通過這個IOCTL最終 調用KVM里面的kvm_set_irq將中斷注入到虛擬的中斷控制器。在kvm中會進一步判斷屬于什么中斷類型,然后在合適的時機寫入vmcs。當然在 KVM_RUN中會不斷的同步虛擬中斷控制器,來獲取需要注入的中斷,這些中斷包括QEMU和KVM本身的,并在重新進入客戶機之前注入中斷。
五、Qemu中內(nèi)存管理
5.1相關配置參數(shù)
QEMU的命令行中有參數(shù):
-m [size=]megs[,slots=n,maxmem=size]用于指定客戶機初始運行時的內(nèi)存大小以及客戶機最大內(nèi)存大小,以及內(nèi)存芯片槽的數(shù)量(DIMM)。
之所以QEMU可以指定最大內(nèi)存、槽等參數(shù),是因為QEMU可以模擬DIMM的熱插拔,客戶機操作系統(tǒng)可以和在真實的系統(tǒng)上一樣,檢測新內(nèi)存被插入或者拔出。也就是說,內(nèi)存熱插拔的粒度是DIMM槽(或者說DIMM集合),而不是最小的byte。
與內(nèi)存相關的數(shù)據(jù)結構:
圖片
PCDIMMDevice和HostMemoryBackend對象都是在QEMU中用戶可見的客戶機內(nèi)存。它們能通過QEMU命令行或者QMP監(jiān)控器接口來管理。
PCDIMMDevice數(shù)據(jù)結構是使用QEMU中的面向對象編程模型QOM定義的,對應的對象和類的數(shù)據(jù)結構如下。通過在QEMU進程中創(chuàng)建一個新的PCDIMMDevice對象,就可以實現(xiàn)內(nèi)存的熱插拔。
值得注意的是,客戶機啟動時的初始化內(nèi)存,可能不會被模擬成PCDIMMDevice設備,也就是說,這部分初始化內(nèi)存不能進行熱插拔。PCDIMMDevice的定義在include/hw/mem/pc-dimm.h中。
typedef struct PCDIMMDevice {
/* private */
DeviceState parent_obj;
/* public */
uint64_t addr;
uint32_t node; //numa node
int32_t slot; //slot編號
HostMemoryBackend *hostmem;
} PCDIMMDevice;
typedef struct PCDIMMDeviceClass {
/* private */
DeviceClass parent_class;
/* public */
MemoryRegion *(*get_memory_region)(PCDIMMDevice *dimm);
} PCDIMMDeviceClass;每個PCDIMMDevice對象都與 HostMemoryBackend對象相關聯(lián)。HostMemoryBackend也是使用QEMU中的面向對象編程模型QOM定義的。HostMemoryBackend定義在include/sysemu/hostmem.h中。HostMemoryBackend對象包含了客戶機內(nèi)存對應的真正的主機內(nèi)存,這些內(nèi)存可以是匿名映射的內(nèi)存,也可以是文件映射內(nèi)存。文件映射的客戶機內(nèi)存允許Linux在物理主機上透明大頁機制的使用(hugetlbfs),并且能夠共享內(nèi)存,從而使其他進程可以訪問客戶機內(nèi)存。
struct HostMemoryBackend {
/* private */
Object parent;
/* protected */
uint64_t size;
bool merge, dump;
bool prealloc, force_prealloc;
DECLARE_BITMAP(host_nodes, MAX_NODES + 1);
HostMemPolicy policy;
MemoryRegion mr;
};
struct HostMemoryBackendClass {
ObjectClass parent_class;
void (*alloc)(HostMemoryBackend *backend, Error **errp);
};HostMemoryBackend對象中的內(nèi)存被實際映射到通過qemu_ram_alloc()函數(shù)(代碼定義在exec.c中)RAMBlock數(shù)據(jù)結構中。每個RAMBlock都有一個指針指向被映射內(nèi)存的起始位置,同時包含一個ram_addr_t的位移變量。ram_addr_t位于全局的命名空間中,因此RAMBlock能夠通過offset來查找。
RAMBlock定義在include/exec/ram_addr.h中。RAMBlock受RCU機制保護,所謂RCU,即Read-COPY-Update。
typedef uint64_t ram_addr_t;
struct RAMBlock {
struct rcu_head rcu; //該數(shù)據(jù)結構受rcu機制保護
struct MemoryRegion *mr;
uint8_t *host; //RAMBlock的內(nèi)存起始位置
ram_addr_t offset; //在所有的RAMBlock中offset
ram_addr_t used_length; //已使用長度
ram_addr_t max_length; //最大分配內(nèi)存
void (*resized)(const char*, uint64_t length, void *host);
uint32_t flags;
/* Protected by iothread lock. */
char idstr[256]; //RAMBlock的ID
/* RCU-enabled, writes protected by the ramlist lock */
QLIST_ENTRY(RAMBlock) next;
int fd; //映射文件的描述符
};所有的RAMBlock保存在全局的RAMBlock的鏈表中,名為RAMList,它有專門的數(shù)據(jù)結構定義。RAMList數(shù)據(jù)結構定義在include/exec/ram_addr.h中,而全局的ram_list變量則定義在exec.c中。因此這個鏈表保存了客戶機的內(nèi)存對應的所有的物理機的實際內(nèi)存信息。
5.2跟蹤臟頁
當客戶機CPU或者DMA將數(shù)據(jù)保存到客戶機內(nèi)存時,需要通知下列一些用戶:
- 熱遷移特性依賴于跟蹤臟頁,因此他們能夠在被改變之后重新傳輸。
- 圖形卡模擬依賴于跟蹤臟的視頻內(nèi)存,用于重畫某些界面。
所有的CPU架構都有內(nèi)存地址空間、有些CPU架構又有一個IO地址空間。它們在QEMU中被表示為AddressSpace數(shù)據(jù)結構,它定義在include/exec/memory.h中。而每個地址空間都包含一個MemoryRegion的樹狀結構,所謂樹狀結構,指的是每個MemoryRegion的內(nèi)部可以含有MemoryRegion,這樣的包含所形成的樹狀結構。
MemoryRegion是聯(lián)系客戶機內(nèi)存和包含這一部分內(nèi)存的RAMBlock。每個MemoryRegion都包含一個在RAMBlock中ram_addr_t類型的offset,每個RAMBlock也有一個MemoryRegion的指針。
MemoryRegion不僅可以表示RAM,也可以表示I/O映射內(nèi)存,在訪問時可以調用read/write回調函數(shù)。這也是硬件從客戶機CPU注冊的訪問被分派到相應的模擬設備的方法。
struct AddressSpace {
/* All fields are private. */
struct rcu_head rcu;
char *name;
MemoryRegion *root;
/* Accessed via RCU. */
struct FlatView *current_map; //AddressSpace的一張平面視圖,它是AddressSpace所有正在使用的MemoryRegion的集合,這是從CPU的視角來看到的。
int ioeventfd_nb;
struct MemoryRegionIoeventfd *ioeventfds;
struct AddressSpaceDispatch *dispatch;
struct AddressSpaceDispatch *next_dispatch;
MemoryListener dispatch_listener;
QTAILQ_ENTRY(AddressSpace) address_spaces_link;
};
struct MemoryRegion {
Object parent_obj;
/* All fields are private - violators will be prosecuted */
const MemoryRegionOps *ops; //與MemoryRegion相關的操作
const MemoryRegionIOMMUOps *iommu_ops;
void *opaque;
MemoryRegion *container;
Int128 size;
hwaddr addr; //在AddressSpace中的地址
void (*destructor)(MemoryRegion *mr);
ram_addr_t ram_addr; //MemoryRegion的起始地址
uint64_t align; //big-endian or little-endian
bool subpage;
bool terminates;
bool romd_mode;
bool ram;
bool skip_dump;
bool readonly; /* For RAM regions */
bool enabled; //如果為true,表示已經(jīng)通知kvm使用這段內(nèi)存
bool rom_device; //是否是只讀內(nèi)存
bool warning_printed; /* For reservations */
bool flush_coalesced_mmio;
bool global_locking;
uint8_t vga_logging_count;
MemoryRegion *alias;
hwaddr alias_offset;
int32_t priority;
bool may_overlap;
QTAILQ_HEAD(subregions, MemoryRegion) subregions;
QTAILQ_ENTRY(MemoryRegion) subregions_link;
QTAILQ_HEAD(coalesced_ranges, CoalescedMemoryRange) coalesced;
const char *name; //MemoryRegion的名字,調試時使用
uint8_t dirty_log_mask; //表示哪種dirty map被使用,共有三種
//IOevent文件描述符的管理
unsigned ioeventfd_nb;
MemoryRegionIoeventfd *ioeventfds;
NotifierList iommu_notify;
};六、Qemu與其他虛擬機管理器對比
在虛擬化的廣袤天地里,Qemu 并非獨自閃耀,還有其他一些虛擬機管理器同樣備受關注,它們各自有著獨特的特點和優(yōu)勢。下面,我們就來深入對比一下 Qemu 與其他常見虛擬機管理器的異同。
6.1 Qemu與 KVM的協(xié)作與差異
KVM,即 Kernel-based Virtual Machine,是基于 Linux 內(nèi)核的虛擬化技術 。它利用硬件虛擬化擴展(如 Intel VT 或 AMD-V)來實現(xiàn)高效的硬件輔助虛擬化,與 Qemu 有著緊密的聯(lián)系,同時也存在一些明顯的差異。
從協(xié)作的角度來看,KVM 和 Qemu 常常攜手合作,共同為用戶提供強大的虛擬化解決方案 。KVM 作為 Linux 內(nèi)核的一部分,提供了虛擬化的核心框架,負責管理 CPU 和內(nèi)存等關鍵資源的虛擬化 。而 Qemu 則作為用戶空間的工具,承擔起模擬各種硬件設備的重任,為虛擬機提供完整的硬件環(huán)境,如模擬網(wǎng)卡、硬盤、顯卡等設備,使得虛擬機能夠像運行在真實硬件上一樣與外部環(huán)境進行交互 。通過這種協(xié)作,KVM 和 Qemu 充分發(fā)揮各自的優(yōu)勢,既利用了硬件虛擬化的高性能,又實現(xiàn)了豐富的硬件模擬功能,為用戶帶來了高效、靈活的虛擬化體驗。
在性能方面,KVM 具有顯著的優(yōu)勢 。由于 KVM 依賴于硬件輔助虛擬化,它可以直接利用 CPU 的虛擬化擴展,大大降低了虛擬化的開銷,使得虛擬機能夠以接近原生系統(tǒng)的性能運行 。對于那些對性能要求極高的應用場景,如大規(guī)模數(shù)據(jù)處理、高性能計算等,KVM 的優(yōu)勢尤為明顯 。相比之下,Qemu 在純軟件模擬模式下,由于所有的硬件模擬都通過軟件實現(xiàn),會產(chǎn)生較高的開銷,性能相對較低 。特別是在處理計算密集型任務時,Qemu 可能會出現(xiàn)性能瓶頸 。然而,當 Qemu 與 KVM 結合使用時,借助 KVM 的硬件加速功能,其性能會得到大幅提升 。
設備支持方面,Qemu 憑借其全系統(tǒng)仿真的特性,展現(xiàn)出了強大的兼容性 。它能夠模擬多種不同架構的硬件設備,支持 x86、ARM、PowerPC、MIPS 等多種處理器架構,這使得 Qemu 在跨平臺開發(fā)和測試中具有獨特的優(yōu)勢 。無論是開發(fā)基于 x86 架構的服務器應用,還是基于 ARM 架構的嵌入式系統(tǒng),Qemu 都能提供相應的模擬環(huán)境 。而 KVM 的設備支持則相對局限于具有特定硬件虛擬化擴展的系統(tǒng),主要適用于基于 x86 架構的服務器場景 。雖然 KVM 也在不斷擴展其設備支持范圍,但在跨平臺兼容性方面,與 Qemu 相比仍有一定差距 。
易用性上,Qemu 的使用相對較為簡單直觀 。它提供了豐富的命令行參數(shù)和圖形化界面工具,用戶可以通過簡單的配置和操作,快速創(chuàng)建和管理虛擬機 。而且,Qemu 對硬件的要求相對較低,即使在不支持硬件虛擬化的設備上也能運行 。KVM 的使用則相對復雜一些,由于它與 Linux 內(nèi)核緊密集成,用戶需要對 Linux 系統(tǒng)有一定的了解,并且需要確保硬件支持虛擬化擴展 。不過,隨著管理工具的不斷發(fā)展,如 virt-manager 等圖形化管理工具的出現(xiàn),KVM 的管理也變得越來越方便 。
6.2 Qemu與 libvirt 的功能區(qū)分
libvirt 是一個用于管理和控制虛擬化技術的工具集,它提供了統(tǒng)一的 API 和命令行工具,支持多種虛擬化技術,包括 Qemu/KVM、Xen、LXC 等 。與 Qemu 相比,libvirt 在功能和定位上有著明顯的區(qū)別。
在虛擬機管理方式上,Qemu 主要通過命令行或者腳本來直接啟動和管理虛擬機 。用戶需要熟悉 Qemu 的各種命令行參數(shù),手動配置虛擬機的各項參數(shù),如內(nèi)存大小、CPU 核心數(shù)、磁盤映像文件等 。這種方式雖然靈活,但對于初學者來說可能具有一定的難度 。而 libvirt 則提供了更為高級和抽象的管理方式 。它通過 XML 配置文件來描述虛擬機的各種屬性和配置,用戶可以通過編輯 XML 文件或者使用 libvirt 提供的命令行工具(如 virsh)、圖形化界面工具(如 virt-manager)來管理虛擬機 。這種方式使得虛擬機的管理更加規(guī)范化和易于操作,尤其適合在生產(chǎn)環(huán)境中進行大規(guī)模的虛擬機管理 。
從功能特點來看,Qemu 專注于硬件模擬和虛擬機的運行,它提供了強大的設備模擬功能,能夠為虛擬機提供逼真的硬件環(huán)境 。Qemu 還支持動態(tài)二進制翻譯等技術,實現(xiàn)了跨架構的虛擬化 。而 libvirt 則更側重于提供統(tǒng)一的管理接口和高級的管理功能 。它不僅可以管理虛擬機的生命周期,如創(chuàng)建、啟動、暫停、關閉、刪除等操作,還提供了諸如虛擬機快照、遷移、資源監(jiān)控等高級功能 。通過 libvirt,用戶可以方便地對多個虛擬機進行集中管理,實現(xiàn)資源的動態(tài)分配和優(yōu)化 。
舉個例子,在一個云計算數(shù)據(jù)中心中,管理員可能會使用 libvirt 來統(tǒng)一管理大量的虛擬機,通過 virsh 命令或者 virt-manager 界面,快速創(chuàng)建、部署和監(jiān)控虛擬機 。而在每個虛擬機內(nèi)部,Qemu 則負責模擬硬件設備,為虛擬機提供運行環(huán)境,確保虛擬機中的操作系統(tǒng)和應用程序能夠正常運行 。
七、使用Qemu虛擬機管理器的優(yōu)勢
7.1靈活性與可定制性
Qemu 虛擬機管理器賦予用戶高度的自由,讓用戶能夠根據(jù)自己的需求隨心所欲地定制虛擬機的各種參數(shù) 。無論是設置虛擬機的 CPU 核心數(shù)、內(nèi)存大小,還是配置虛擬硬盤的容量和類型,甚至是調整虛擬網(wǎng)卡的網(wǎng)絡配置,用戶都可以通過簡單的命令行參數(shù)或者配置文件輕松實現(xiàn) 。例如,在進行大數(shù)據(jù)處理的性能測試時,用戶可以根據(jù)測試需求,將虛擬機的 CPU 核心數(shù)設置為 8 個,內(nèi)存設置為 16GB,以模擬真實的大數(shù)據(jù)處理環(huán)境 。
這種高度的靈活性和可定制性,使得 Qemu 能夠滿足各種復雜的硬件虛擬化需求,無論是進行簡單的開發(fā)測試,還是搭建復雜的云計算環(huán)境,Qemu 都能應對自如 。而且,Qemu 還支持對虛擬機進行動態(tài)調整,用戶可以在虛擬機運行過程中,根據(jù)實際需求動態(tài)增加或減少 CPU 核心數(shù)、內(nèi)存大小等資源,無需重啟虛擬機,大大提高了資源的利用率和使用效率 。
7.2廣泛的硬件和系統(tǒng)支持
Qemu 對硬件和操作系統(tǒng)的兼容性堪稱一絕 。它支持 x86、ARM、PowerPC、MIPS、RISC-V 等多種硬件架構,這使得開發(fā)者可以在同一臺物理計算機上模擬不同架構的硬件環(huán)境,進行跨平臺的開發(fā)和測試 。無論是開發(fā)基于 x86 架構的桌面應用,還是基于 ARM 架構的嵌入式系統(tǒng),Qemu 都能提供相應的模擬環(huán)境 。
在操作系統(tǒng)支持方面,Qemu 同樣表現(xiàn)出色,它幾乎支持所有主流的操作系統(tǒng),如 Windows、Linux、macOS、FreeBSD、Solaris 等 。用戶可以在 Qemu 虛擬機中輕松安裝和運行這些操作系統(tǒng),無需擔心兼容性問題 。例如,安全研究人員可以利用 Qemu 創(chuàng)建一個包含 Windows 操作系統(tǒng)和各種應用程序的虛擬機,用于進行惡意軟件分析和漏洞挖掘 。這種廣泛的硬件和系統(tǒng)支持,使得 Qemu 成為了開發(fā)者和技術愛好者的得力助手,為他們的工作和研究提供了極大的便利 。
7.3強大的社區(qū)與生態(tài)
Qemu 擁有一個龐大且活躍的開源社區(qū) 。在這個社區(qū)中,來自世界各地的開發(fā)者和技術愛好者們積極參與 Qemu 的開發(fā)和維護,不斷為 Qemu 貢獻新的功能和特性 。社區(qū)成員們還會在社區(qū)論壇、郵件列表等平臺上分享自己的使用經(jīng)驗、技術心得和解決方案,當用戶在使用 Qemu 過程中遇到問題時,可以在社區(qū)中尋求幫助,往往能得到其他成員的熱心解答和支持 。
同時,社區(qū)還提供了豐富的文檔資源,包括官方文檔、用戶手冊、教程等,這些文檔詳細介紹了 Qemu 的使用方法、工作原理和開發(fā)指南,無論是初學者還是有經(jīng)驗的用戶,都能從中獲取到有用的信息 。此外,Qemu 還有著豐富的生態(tài)系統(tǒng),它與許多其他開源項目和工具緊密集成,如 KVM、libvirt、OpenStack 等 。這些集成使得 Qemu 的功能得到了進一步擴展和增強,用戶可以根據(jù)自己的需求,選擇合適的工具和技術與 Qemu 搭配使用,構建出更加完善的虛擬化解決方案 。






















