1.KVM架構
KVM 基本上有兩個組件構成:架構
1. kvm 驅動 如今已是Linux內核的一個模塊了,它的做用主要是負責虛擬機的建立,虛擬內存的分配 虛擬CPU寄存器的讀寫和虛擬cpu的運行函數
2. 另外一個組件是 Qemu QEMU是一個通用的開源機器模擬器和虛擬器,其主要的功能是用於模擬虛擬機的用戶空間組件,提供io 設備模型,訪問外設的途徑oop
Qemu 是什麼?性能
Qemu 是純軟件設計的虛擬化模擬器,幾乎能夠模擬任何硬件設備,咱們最熟悉的就是可以模擬一臺可以獨立運行操做系統的虛擬機,虛擬機認爲本身和虛擬機打交道,但實際上是和Qemu模擬出來的硬件打交道,Qemu 將這些真正的指令轉譯給真正的硬件ui
正由於Qemu是純軟件實現的,全部的指令都要通過qemu過一手,性能很是低,因此,在生產環境中,因此在生產環境中,Qemu配合KVM來完成虛擬化工做,由於kvm是硬件輔助的虛擬化技術,主要負責比較繁瑣的cpu虛擬化和內存虛擬化,而QEMU則負責IO設備虛擬化,二者合做發揮自身的優點,相得益彰spa
從本質上看,虛擬出的每一個虛擬機對應宿主機上的一個QEMU 進程,而虛擬機的執行線路(cpu線路,io線路)對用qemu 進程中的一個線程,操作系統
下面經過啓動一個虛擬機來說解kvm 與QEmu是怎麼交互工做的線程
// 第一步,獲取到 KVM 句柄翻譯
kvmfd = open("/dev/kvm", O_RDWR);設計
// 第二步,建立虛擬機,獲取到虛擬機句柄。
vmfd = ioctl(kvmfd, KVM_CREATE_VM, 0);
// 第三步,爲虛擬機映射內存,還有其餘的 PCI,信號處理的初始化。
ioctl(kvmfd, KVM_SET_USER_MEMORY_REGION, &mem);
// 第四步,將虛擬機鏡像映射到內存,至關於物理機的 boot 過程,把鏡像映射到內存。
// 第五步,建立 vCPU,併爲 vCPU 分配內存空間。
ioctl(kvmfd, KVM_CREATE_VCPU, vcpuid);
vcpu->kvm_run_mmap_size = ioctl(kvm->dev_fd, KVM_GET_VCPU_MMAP_SIZE, 0); // 第五步,建立 vCPU 個數的線程並運行虛擬機。
ioctl(kvm->vcpus->vcpu_fd, KVM_RUN, 0);
// 第六步,線程進入循環,並捕獲虛擬機退出緣由,作相應的處理。
for (;;) { ioctl(KVM_RUN) switch (exit_reason) {
case KVM_EXIT_IO: /* ... */ case KVM_EXIT_HLT: /* ... */
} }
// 這裏的退出並不必定是虛擬機關機,
// 虛擬機若是遇到 I/O 操做,訪問硬件設備,缺頁中斷等都會退出執行,
// 退出執行能夠理解爲將 CPU 執行上下文返回到 Qemu。
Qemu 軟件實現虛擬化的思路是二進制指令翻譯技術,主要是提取客戶端的代碼指令,而後將其翻譯成TCG中間代碼,最後再將中間代碼 翻譯成物理機指定架構的代碼,如X86體系就翻譯成其支持的代碼形式,ARM架構同理,
因此,從宏觀上看,源碼結構主要包含如下幾個部分:
· /vl.c:最主要的模擬循環,虛擬機環境初始化,和 CPU 的執行。
· /target-arch/translate.c:將 guest 代碼翻譯成不一樣架構的 TCG 操做碼。
· /tcg/tcg.c:主要的 TCG 代碼。
· /tcg/arch/tcg-target.c:將 TCG 代碼轉化生成主機代碼。
· /cpu-exec.c:主要尋找下一個二進制翻譯代碼塊,若是沒有找到就請求獲得下一個代碼塊,而且操做生成的代碼塊。
其中,涉及的主要幾個函數以下:
函數 |
路徑 |
註釋 |
main_loop |
{/vl.c} |
不少條件的判斷,如電源是否斷等 |
qemu_main_loop_start |
{/cpus.c} |
分時運行 CPU 核 |
struct CPUState |
{/target-xyz/cpu.h} |
CPU 狀態結構體 |
cpu_exec |
{/cpu-exec.c} |
主要的執行循環 |
struct TranslationBlock |
{/exec-all.h} |
TB(二進制翻譯代碼塊) 結構體 |
cpu_gen_code |
{translate-all.c} |
初始化真正代碼生成 |
tcg_gen_code |
{/tcg/tcg.c} |
tcg 代碼翻譯成 host 代碼 |
知道了這個整體的代碼結構,再去具體瞭解每個模塊可能會相對容易一點。
KVM做用
kvm基本結構
Kvm 已是內核模塊,被看做是一個標準的Linux字符集設備 /dev/kvm
Qemu 經過kvmlib接口,用fd 經過ioctl 向設備驅動來發送建立,運行虛擬機命令,設備驅動/dev/kvm 就會來解析命令(kvm_dev_ioctl 在函數kvm_main.c中)
如下爲kvm_dev_ioctl函數 執行的整個代碼流程:
Kvm 模塊讓Linux 主機成爲一個虛擬機監視/管理器(VMM),而且在原有的Linux 兩種執行模式的基礎上,新增長了客戶模式,客戶模式擁有本身的用戶模式和內核模式,在虛擬機運行時,
三種運行模式分別爲:
內核模式: 實現客戶模式的切換,處理由於IO或者其餘指令引發的客戶模式退出(VM_EXIT) kvm 工做在 這 個模式下,
用戶模式:表明用戶在IO模式下,執行QEMU 指令;
客戶模式:執行非IO的客戶代碼,虛擬機運行在這種模式下
在kvm的模型中,每個guest os 都是做爲一個標準的Linux進程,均可以使用Linux進程管理管理命令!
這裏假如Qemu 經過ioctl 發出KVM_CREAT_VM指令,建立一個VM後,qemu須要發送一個命令給VM,如KVM_CREAT_VCPU,這些命令固然也是經過ioctl發送的,用戶程序中用ioctl經過發送KVM_CREAT_VM 指令後獲得的返回值就是fd(KVM_VM),fd是建立的指向特定虛擬機實例的文件描述符,以後利用這個fd發送命令給VM進行訪問控制。KVM 解析這些命令kvm_vm_ioctl
2.KVM工做原理
Kvm 工做原理的基本闡釋:
用戶模式的qume利用libkvm 經過ioctl進入內核模式,kvm 模塊爲虛擬機建立虛擬內存,虛擬cpu後執行VMLUACH指令進入客戶模式。加載guest os並執行。若是guest os 發生外部中斷,或者影子頁表缺頁之類的狀況,會暫停guest os的執行,退出客戶模式出行異常處理,以後從新進入客戶模式,執行客戶代碼,若是發生iO事件或者信號隊列中有信號到達,就會進入用戶模式處理。
處理狀況以下圖
什麼是虛擬機管理器vmm ,虛擬機管理器(vmm)有哪些,區別是什麼?
虛擬機管理器(virtual machine monitor)是一個宿主程序,它支持一臺計算機執行多個徹底相同的執行環境,每位用戶都會感受本身在一臺獨立的計算機上,與其餘用戶相隔離的計算機上操做,儘管事實上爲每位用戶提供服務的都是同一臺機器,在此種狀況下,一臺虛擬機就是由一個潛在的控制程序管理的操做系統
Vmm 是在底層對其上的虛擬機的管理和支持,之前的虛擬機必須如今一個做系統上安裝虛擬機操做軟件,而後再在操做軟件上安裝虛擬機,安裝系統和應用。但如今的intel 的cpu 已經對虛擬化技術作了硬件支持,大多數的vmm可直接裝在裸機上,在其上在安裝幾個虛擬機,這樣就大大提高了虛擬化環境下的性能體驗