學習 KVM 的系列文章:
- (1)介紹和安裝
- (2)CPU 和 內存虛擬化
- (3)I/O QEMU 全虛擬化和准虛擬化(Para-virtulizaiton)
- (4)I/O PCI/PCIe設備直接分配和 SR-IOV
- (5)libvirt 介紹
- (6)Nova 通過 libvirt 管理 QEMU/KVM 虛機
- (7)快照 (snapshot)
- (8)遷移 (migration)
1. 為什么需要 CPU 虛擬化
- 操作系統(內核)需要直接訪問硬件和內存,因此它的代碼需要運行在最高運行級別 Ring0上,這樣它可以使用特權指令,控制中斷、修改頁表、訪問設備等等。
- 應用程序的代碼運行在最低運行級別上ring3上,不能做受控操作。如果要做,比如要訪問磁盤,寫文件,那就要通過執行系統調用(函數),執行系統調用的時候,CPU的運行級別會發生從ring3到ring0的切換,並跳轉到系統調用對應的內核代碼位置執行,這樣內核就為你完成了設備訪問,完成之后再從ring0返回ring3。這個過程也稱作用戶態和內核態的切換。
1.1 基於二進制翻譯的全虛擬化(Full Virtualization with Binary Translation)
1.2. 超虛擬化(或者半虛擬化/操作系統輔助虛擬化 Paravirtualization)
1.3. 硬件輔助的全虛擬化
|
|
利用二進制翻譯
的全虛擬化
|
硬件輔助虛擬化
|
操作系統協助
/
半虛擬化
|
|
實現技術
|
BT
和直接執行
|
遇到特權指令轉到root模式執行
|
Hypercall
|
|
客戶操作系統修改
/
兼容性
|
無需修改客戶操作系統,最佳兼容性
|
無需修改客戶操作系統,最佳兼容性
|
客戶操作系統需要修改來支持hypercall,因此它不能運行在物理硬件本身或其他的hypervisor上,兼容性差,不支持Windows
|
|
性能
|
差
|
全虛擬化下,CPU需要在兩種模式之間切換,帶來性能開銷;但是,其性能在逐漸逼近半虛擬化。
|
好。半虛擬化下CPU性能開銷幾乎為0,虛機的性能接近於物理機。
|
|
應用廠商
|
VMware Workstation/QEMU/Virtual PC
|
VMware ESXi/Microsoft Hyper-V/Xen 3.0/KVM
|
Xen
|
2. KVM CPU 虛擬化
KVM 是基於CPU 輔助的全虛擬化方案,它需要CPU虛擬化特性的支持。
2.1. CPU 物理特性
這個命令查看主機上的CPU 物理情況:
[s1@rh65 ~]$ numactl --hardware available: 2 nodes (0-1) //2顆CPU node 0 cpus: 0 1 2 3 4 5 12 13 14 15 16 17 //這顆 CPU 有8個內核 node 0 size: 12276 MB node 0 free: 7060 MB node 1 cpus: 6 7 8 9 10 11 18 19 20 21 22 23 node 1 size: 8192 MB node 1 free: 6773 MB node distances: node 0 1 0: 10 21 1: 21 10
要支持 KVM, Intel CPU 的 vmx 或者 AMD CPU 的 svm 擴展必須生效了:
[root@rh65 s1]# egrep "(vmx|svm)" /proc/cpuinfo flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx pdpe1gb rdtscp lm constant_tsc arch_perfmon pebs bts rep_good xtopology nonstop_tsc aperfmperf pni pclmulqdq dtes64 monitor ds_cpl vmx smx est tm2 ssse3 cx16 xtpr pdcm pcid dca sse4_1 sse4_2 popcnt aes lahf_lm arat epb dts tpr_shadow vnmi flexpriority ept vpid
2.2 多 CPU 服務器架構:SMP,NMP,NUMA
從系統架構來看,目前的商用服務器大體可以分為三類:
- 多處理器結構 (SMP : Symmetric Multi-Processor):所有的CPU共享全部資源,如總線,內存和I/O系統等,操作系統或管理數據庫的復本只有一個,這種系統有一個最大的特點就是共享所有資源。多個CPU之間沒有區別,平等地訪問內存、外設、一個操作系統。SMP 服務器的主要問題,那就是它的擴展能力非常有限。實驗證明, SMP 服務器 CPU 利用率最好的情況是 2 至 4 個 CPU 。
- 海量並行處理結構 (MPP : Massive Parallel Processing) :NUMA 服務器的基本特征是具有多個 CPU 模塊,每個 CPU 模塊由多個 CPU( 如 4 個 ) 組成,並且具有獨立的本地內存、 I/O 槽口等。在一個物理服務器內可以支持上百個 CPU 。但 NUMA 技術同樣有一定缺陷,由於訪問遠地內存的延時遠遠超過本地內存,因此當 CPU 數量增加時,系統性能無法線性增加。
- MPP 模式則是一種分布式存儲器模式,能夠將更多的處理器納入一個系統的存儲器。一個分布式存儲器模式具有多個節點,每個節點都有自己的存儲器,可以配置為SMP模式,也可以配置為非SMP模式。單個的節點相互連接起來就形成了一個總系統。MPP可以近似理解成一個SMP的橫向擴展集群,MPP一般要依靠軟件實現。
- 非一致存儲訪問結構 (NUMA : Non-Uniform Memory Access):它由多個 SMP 服務器通過一定的節點互聯網絡進行連接,協同工作,完成相同的任務,從用戶的角度來看是一個服務器系統。其基本特征是由多個 SMP 服務器 ( 每個 SMP 服務器稱節點 ) 通過節點互聯網絡連接而成,每個節點只訪問自己的本地資源 ( 內存、存儲等 ) ,是一種完全無共享 (Share Nothing) 結構。
詳細描述可以參考 SMP、NUMA、MPP體系結構介紹。
查看你的服務器的 CPU 架構:
[root@rh65 s1]# uname -a Linux rh65 2.6.32-431.el6.x86_64 #1 SMP Sun Nov 10 22:19:54 EST 2013 x86_64 x86_64 x86_64 GNU/Linux #這服務器是 SMP 架構
2.2 KVM CPU 虛擬化
2.2.1 KVM 虛機的創建過程

可見:
(1)qemu-kvm 通過對 /dev/kvm 的 一系列 ICOTL 命令控制虛機,比如
open("/dev/kvm", O_RDWR|O_LARGEFILE) = 3 ioctl(3, KVM_GET_API_VERSION, 0) = 12 ioctl(3, KVM_CHECK_EXTENSION, 0x19) = 0 ioctl(3, KVM_CREATE_VM, 0) = 4 ioctl(3, KVM_CHECK_EXTENSION, 0x4) = 1 ioctl(3, KVM_CHECK_EXTENSION, 0x4) = 1 ioctl(4, KVM_SET_TSS_ADDR, 0xfffbd000) = 0 ioctl(3, KVM_CHECK_EXTENSION, 0x25) = 0 ioctl(3, KVM_CHECK_EXTENSION, 0xb) = 1 ioctl(4, KVM_CREATE_PIT, 0xb) = 0 ioctl(3, KVM_CHECK_EXTENSION, 0xf) = 2 ioctl(3, KVM_CHECK_EXTENSION, 0x3) = 1 ioctl(3, KVM_CHECK_EXTENSION, 0) = 1 ioctl(4, KVM_CREATE_IRQCHIP, 0) = 0 ioctl(3, KVM_CHECK_EXTENSION, 0x1a) = 0
(2)一個 KVM 虛機即一個 Linux qemu-kvm 進程,與其他 Linux 進程一樣被Linux 進程調度器調度。
(3)KVM 虛機包括虛擬內存、虛擬CPU和虛機 I/O設備,其中,內存和 CPU 的虛擬化由 KVM 內核模塊負責實現,I/O 設備的虛擬化由 QEMU 負責實現。
(3)KVM戶機系統的內存是 qumu-kvm 進程的地址空間的一部分。
(4)KVM 虛機的 vCPU 作為 線程運行在 qemu-kvm 進程的上下文中。
vCPU、QEMU 進程、LInux 進程調度和物理CPU之間的邏輯關系:

2.2.2 因為 CPU 中的虛擬化功能的支持,並不存在虛擬的 CPU,KVM Guest 代碼是運行在物理 CPU 之上
根據上面的 1.3 章節,支持虛擬化的 CPU 中都增加了新的功能。以 Intel VT 技術為例,它增加了兩種運行模式:VMX root 模式和 VMX nonroot 模式。通常來講,主機操作系統和 VMM 運行在 VMX root 模式中,客戶機操作系統及其應用運行在 VMX nonroot 模式中。因為兩個模式都支持所有的 ring,因此,客戶機可以運行在它所需要的 ring 中(OS 運行在 ring 0 中,應用運行在 ring 3 中),VMM 也運行在其需要的 ring 中 (對 KVM 來說,QEMU 運行在 ring 3,KVM 運行在 ring 0)。CPU 在兩種模式之間的切換稱為 VMX 切換。從 root mode 進入 nonroot mode,稱為 VM entry;從 nonroot mode 進入 root mode,稱為 VM exit。可見,CPU 受控制地在兩種模式之間切換,輪流執行 VMM 代碼和 Guest OS 代碼。
對 KVM 虛機來說,運行在 VMX Root Mode 下的 VMM 在需要執行 Guest OS 指令時執行 VMLAUNCH 指令將 CPU 轉換到 VMX non-root mode,開始執行客戶機代碼,即 VM entry 過程;在 Guest OS 需要退出該 mode 時,CPU 自動切換到 VMX Root mode,即 VM exit 過程。可見,KVM 客戶機代碼是受 VMM 控制直接運行在物理 CPU 上的。QEMU 只是通過 KVM 控制虛機的代碼被 CPU 執行,但是它們本身並不執行其代碼。也就是說,CPU 並沒有真正的被虛級化成虛擬的 CPU 給客戶機使用。
這篇文章 是關於 vSphere 中 CPU 虛擬化的,我覺得它和 KVM CPU 虛擬化存在很大的一致。下圖是使用 2 socket 2 core 共 4 個 vCPU 的情形:

幾個概念:socket (顆,CPU 的物理單位),core (核,每個 CPU 中的物理內核),thread (超線程,通常來說,一個 CPU core 只提供一個 thread,這時客戶機就只看到一個 CPU;但是,超線程技術實現了 CPU 核的虛擬化,一個核被虛擬化出多個邏輯 CPU,可以同時運行多個線程)。
上圖分三層,他們分別是是VM層,VMKernel層和物理層。對於物理服務器而言,所有的CPU資源都分配給單獨的操作系統和上面運行的應用。應用將請求先發送給操作系統,然后操作系統調度物理的CPU資源。在虛擬化平台比如 KVM 中,在VM層和物理層之間加入了VMkernel層,從而允許所有的VM共享物理層的資源。VM上的應用將請求發送給VM上的操作系統,然后操縱系統調度Virtual CPU資源(操作系統認為Virtual CPU和物理 CPU是一樣的),然后VMkernel層對多個物理CPU Core進行資源調度,從而滿足Virtual CPU的需要。在虛擬化平台中OS CPU Scheduler和Hyperviisor CPU Scheduler都在各自的領域內進行資源調度。
KVM 中,可以指定 socket,core 和 thread 的數目,比如 設置 “-smp 5,sockets=5,cores=1,threads=1”,則 vCPU 的數目為 5*1*1 = 5。客戶機看到的是基於 KVM vCPU 的 CPU 核,而 vCPU 作為 QEMU 線程被 Linux 作為普通的線程/輕量級進程調度到物理的 CPU 核上。至於你是該使用多 socket 和 多core,這篇文章 有仔細的分析,其結論是在 VMware ESXi 上,性能沒什么區別,只是某些客戶機操作系統會限制物理 CPU 的數目,這種情況下,可以使用少 socket 多 core。
2.2.3 客戶機系統的代碼是如何運行的
一個普通的 Linux 內核有兩種執行模式:內核模式(Kenerl)和用戶模式 (User)。為了支持帶有虛擬化功能的 CPU,KVM 向 Linux 內核增加了第三種模式即客戶機模式(Guest),該模式對應於 CPU 的 VMX non-root mode。

KVM 內核模塊作為 User mode 和 Guest mode 之間的橋梁:
- User mode 中的 QEMU-KVM 會通過 ICOTL 命令來運行虛擬機
- KVM 內核模塊收到該請求后,它先做一些准備工作,比如將 VCPU 上下文加載到 VMCS (virtual machine control structure)等,然后驅動 CPU 進入 VMX non-root 模式,開始執行客戶機代碼
三種模式的分工為:
- Guest 模式:執行客戶機系統非 I/O 代碼,並在需要的時候驅動 CPU 退出該模式
- Kernel 模式:負責將 CPU 切換到 Guest mode 執行 Guest OS 代碼,並在 CPU 退出 Guest mode 時回到 Kenerl 模式
- User 模式:代表客戶機系統執行 I/O 操作

(來源)
QEMU-KVM 相比原生 QEMU 的改動:
- 原生的 QEMU 通過指令翻譯實現 CPU 的完全虛擬化,但是修改后的 QEMU-KVM 會調用 ICOTL 命令來調用 KVM 模塊。
- 原生的 QEMU 是單線程實現,QEMU-KVM 是多線程實現。
主機 Linux 將一個虛擬視作一個 QEMU 進程,該進程包括下面幾種線程:
- I/O 線程用於管理模擬設備
- vCPU 線程用於運行 Guest 代碼
- 其它線程,比如處理 event loop,offloaded tasks 等的線程
在我的測試環境中(RedHata Linux 作 Hypervisor):
| smp 設置的值 | 線程數 | 線程 |
| 4 | 8 | 1 個主線程(I/O 線程)、4 個 vCPU 線程、3 個其它線程 |
| 6 | 10 | 1 個主線程(I/O 線程)、6 個 vCPU 線程、3 個其它線程 |
這篇文章 談談了這些線程的情況。

(來源)
| 客戶機代碼執行(客戶機線程) | I/O 線程 | 非 I/O 線程 |
| 虛擬CPU(主機 QEMU 線程) | QEMU I/O 線程 | QEMU vCPU 線程 |
| 物理 CPU | 物理 CPU 的 VMX non-root 模式中 | 物理 CPU 的 VMX non-root 模式中 |
2.2.4 從客戶機線程到物理 CPU 的兩次調度
要將客戶機內的線程調度到某個物理 CPU,需要經歷兩個過程:
- 客戶機線程調度到客戶機物理CPU 即 KVM vCPU,該調度由客戶機操作系統負責,每個客戶機操作系統的實現方式不同。在 KVM 上,vCPU 在客戶機系統看起來就像是物理 CPU,因此其調度方法也沒有什么不同。
- vCPU 線程調度到物理 CPU 即主機物理 CPU,該調度由 Hypervisor 即 Linux 負責。
KVM 使用標准的 Linux 進程調度方法來調度 vCPU 進程。Linux 系統中,線程和進程的區別是 進程有獨立的內核空間,線程是代碼的執行單位,也就是調度的基本單位。Linux 中,線程是就是輕量級的進程,也就是共享了部分資源(地址空間、文件句柄、信號量等等)的進程,所以線程也按照進程的調度方式來進行調度。
(1)Linux 進程調度原理可以參考 這篇文章 和 這篇文章。通常情況下,在SMP系統中,Linux內核的進程調度器根據自有的調度策略將系統中的一個可運行(runable)進程調度到某個CPU上執行。下面是 Linux 進程的狀態機:

(2)處理器親和性:可以設置 vCPU 在指定的物理 CPU 上運行,具體可以參考這篇文章 和 這篇文章。
根據 Linux 進程調度策略,可以看出,在 Linux 主機上運行的 KVM 客戶機 的總 vCPU 數目最好是不要超過物理 CPU 內核數,否則,會出現線程間的 CPU 內核資源競爭,導致有虛機因為 vCPU 進程等待而導致速度很慢。
關於這兩次調度,業界有很多的研究,比如上海交大的論文 Schedule Processes, not VCPUs 提出動態地減少 vCPU 的數目即減少第二次調度。
另外,這篇文章 談到的是 vSphere CPU 的調度方式,有空的時候可以研究下並和 KVM vCPU 的調度方式進行比較。
2.3 客戶機CPU結構和模型
KVM 支持 SMP 和 NUMA 多CPU架構的主機和客戶機。對 SMP 類型的客戶機,使用 “-smp”參數:
-smp <n>[,cores=<ncores>][,threads=<nthreads>][,sockets=<nsocks>][,maxcpus=<maxcpus>]
對 NUMA 類型的客戶機,使用 “-numa”參數:
-numa <nodes>[,mem=<size>][,cpus=<cpu[-cpu>]][,nodeid=<node>]
[root@rh65 s1]# kvm -cpu ? x86 Opteron_G5 AMD Opteron 63xx class CPU x86 Opteron_G4 AMD Opteron 62xx class CPU x86 Opteron_G3 AMD Opteron 23xx (Gen 3 Class Opteron) x86 Opteron_G2 AMD Opteron 22xx (Gen 2 Class Opteron) x86 Opteron_G1 AMD Opteron 240 (Gen 1 Class Opteron) x86 Haswell Intel Core Processor (Haswell) x86 SandyBridge Intel Xeon E312xx (Sandy Bridge) x86 Westmere Westmere E56xx/L56xx/X56xx (Nehalem-C) x86 Nehalem Intel Core i7 9xx (Nehalem Class Core i7) x86 Penryn Intel Core 2 Duo P9xxx (Penryn Class Core 2) x86 Conroe Intel Celeron_4x0 (Conroe/Merom Class Core 2) x86 cpu64-rhel5 QEMU Virtual CPU version (cpu64-rhel5) x86 cpu64-rhel6 QEMU Virtual CPU version (cpu64-rhel6) x86 n270 Intel(R) Atom(TM) CPU N270 @ 1.60GHz x86 athlon QEMU Virtual CPU version 0.12.1 x86 pentium3 x86 pentium2 x86 pentium x86 486 x86 coreduo Genuine Intel(R) CPU T2600 @ 2.16GHz x86 qemu32 QEMU Virtual CPU version 0.12.1 x86 kvm64 Common KVM processor x86 core2duo Intel(R) Core(TM)2 Duo CPU T7700 @ 2.40GHz x86 phenom AMD Phenom(tm) 9550 Quad-Core Processor x86 qemu64 QEMU Virtual CPU version 0.12.1 Recognized CPUID flags: f_edx: pbe ia64 tm ht ss sse2 sse fxsr mmx acpi ds clflush pn pse36 pat cmov mca pge mtrr sep apic cx8 mce pae msr tsc pse de vme fpu f_ecx: hypervisor rdrand f16c avx osxsave xsave aes tsc-deadline popcnt movbe x2apic sse4.2|sse4_2 sse4.1|sse4_1 dca pcid pdcm xtpr cx16 fma cid ssse3 tm2 est smx vmx ds_cpl monitor dtes64 pclmulqdq|pclmuldq pni|sse3 extf_edx: 3dnow 3dnowext lm|i64 rdtscp pdpe1gb fxsr_opt|ffxsr fxsr mmx mmxext nx|xd pse36 pat cmov mca pge mtrr syscall apic cx8 mce pae msr tsc pse de vme fpu extf_ecx: perfctr_nb perfctr_core topoext tbm nodeid_msr tce fma4 lwp wdt skinit xop ibs osvw 3dnowprefetch misalignsse sse4a abm cr8legacy extapic svm cmp_legacy lahf_lm [root@rh65 s1]#
每個 Hypervisor 都有自己的策略,來定義默認上哪些CPU功能會被暴露給客戶機。至於哪些功能會被暴露給客戶機系統,取決於客戶機的配置。qemu32 和 qemu64 是基本的客戶機 CPU 模型,但是還有其他的模型可以使用。你可以使用 qemu-kvm 命令的 -cpu <model> 參數來指定客戶機的 CPU 模型,還可以附加指定的 CPU 特性。"-cpu" 會將該指定 CPU 模型的所有功能全部暴露給客戶機,即使某些特性在主機的物理CPU上不支持,這時候QEMU/KVM 會模擬這些特性,因此,這時候也許會出現一定的性能下降。
RedHat Linux 6 上使用默認的 cpu64-rhe16 作為客戶機 CPU model:

你可以指定特定的 CPU model 和 feature:
qemu-kvm -cpu Nehalem,+aes

你也可以直接使用 -cpu host,這樣的話會客戶機使用和主機相同的 CPU model。
2.4 客戶機 vCPU 數目的分配方法
- 不是客戶機的 vCPU 越多,其性能就越好,因為線程切換會耗費大量的時間;應該根據負載需要分配最少的 vCPU。
- 主機上的客戶機的 vCPU 總數不應該超過物理 CPU 內核總數。不超過的話,就不存在 CPU 競爭,每個 vCPU 線程在一個物理 CPU 核上被執行;超過的話,會出現部分線程等待 CPU 以及一個 CPU 核上的線程之間的切換,這會有 overhead。
- 將負載分為計算負載和 I/O 負載,對計算負載,需要分配較多的 vCPU,甚至考慮 CPU 親和性,將指定的物理 CPU 核分給給這些客戶機。
這篇文章 (http://my.oschina.net/chape/blog/173981) 介紹了一些指導性方法,摘要如下:
我們來假設一個主機有 2 個socket,每個 socket 有 4 個core。主頻2.4G MHZ 那么一共可用的資源是 2*4*2.4G= 19.2G MHZ。假設主機上運行了三個VM,VM1和VM2設置為1socket*1core,VM3設置為1socket*2core。那么VM1和VM2分別有1個vCPU,而VM3有2個vCPU。假設其他設置為缺省設置。
那么三個VM獲得該主機CPU資源分配如下:VM1:25%; VM2:25%; VM3:50%
假設運行在VM3上的應用支持多線程,那么該應用可以充分利用到所非配的CPU資源。2vCPU的設置是合適的。假設運行在VM3上的應用不支持多線程,該應用根本無法同時使用利用2個vCPU. 與此同時,VMkernal層的CPU Scheduler必須等待物理層中兩個空閑的pCPU,才開始資源調配來滿足2個vCPU的需要。在僅有2vCPU的情況下,對該VM的性能不會有太大負面影響。但如果分配4vCPU或者更多,這種資源調度上的負擔有可能會對該VM上運行的應用有很大負面影響。
確定 vCPU 數目的步驟。假如我們要創建一個VM,以下幾步可以幫助確定合適的vCPU數目
1 了解應用並設置初始值
該應用是否是關鍵應用,是否有Service Level Agreement。一定要對運行在虛擬機上的應用是否支持多線程深入了解。咨詢應用的提供商是否支持多線程和SMP(Symmetricmulti-processing)。參考該應用在物理服務器上運行時所需要的CPU個數。如果沒有參照信息,可設置1vCPU作為初始值,然后密切觀測資源使用情況。
2 觀測資源使用情況
確定一個時間段,觀測該虛擬機的資源使用情況。時間段取決於應用的特點和要求,可以是數天,甚至數周。不僅觀測該VM的CPU使用率,而且觀測在操作系統內該應用對CPU的占用率。特別要區分CPU使用率平均值和CPU使用率峰值。
假如分配有4個vCPU,如果在該VM上的應用的CPU
- 使用峰值等於25%, 也就是僅僅能最多使用25%的全部CPU資源,說明該應用是單線程的,僅能夠使用一個vCPU (4 * 25% = 1 )
- 平均值小於38%,而峰值小於45%,考慮減少 vCPU 數目
- 平均值大於75%,而峰值大於90%,考慮增加 vCPU 數目
3 更改vCPU數目並觀測結果
每次的改動盡量少,如果可能需要4vCPU,先設置2vCPU在觀測性能是否可以接受。
2. KVM 內存虛擬化
2.1 內存虛擬化的概念
- 軟件方式:通過軟件實現內存地址的翻譯,比如 Shadow page table (影子頁表)技術
- 硬件實現:基於 CPU 的輔助虛擬化功能,比如 AMD 的 NPT 和 Intel 的 EPT 技術
2.2 KVM 內存虛擬化
- AMD 平台上的 NPT (Nested Page Tables) 技術
- Intel 平台上的 EPT (Extended Page Tables)技術
EPT 和 NPT采用類似的原理,都是作為 CPU 中新的一層,用來將客戶機的物理地址翻譯為主機的物理地址。關於 EPT, Intel 官方文檔中的技術如下(實在看不懂...)

EPT的好處是,它的兩階段記憶體轉換,特點就是將 Guest Physical Address → System Physical Address,VMM不用再保留一份 SPT (Shadow Page Table),以及以往還得經過 SPT 這個轉換過程。除了降低各部虛擬機器在切換時所造成的效能損耗外,硬體指令集也比虛擬化軟體處理來得可靠與穩定。
2.3 KSM (Kernel SamePage Merging 或者 Kernel Shared Memory)
KSM 在 Linux 2.6.32 版本中被加入到內核中。
2.3.1 原理
其原理是,KSM 作為內核中的守護進程(稱為 ksmd)存在,它定期執行頁面掃描,識別副本頁面並合並副本,釋放這些頁面以供它用。因此,在多個進程中,Linux將內核相似的內存頁合並成一個內存頁。這個特性,被KVM用來減少多個相似的虛擬機的內存占用,提高內存的使用效率。由於內存是共享的,所以多個虛擬機使用的內存減少了。這個特性,對於虛擬機使用相同鏡像和操作系統時,效果更加明顯。但是,事情總是有代價的,使用這個特性,都要增加內核開銷,用時間換空間。所以為了提高效率,可以將這個特性關閉。
2.3.2 好處
其好處是,在運行類似的客戶機操作系統時,通過 KSM,可以節約大量的內存,從而可以實現更多的內存超分,運行更多的虛機。
2.3.3 合並過程
(1)初始狀態:

(2)合並后:

(3)Guest 1 寫內存后:

2.4 KVM Huge Page Backed Memory (巨頁內存技術)
這是KVM虛擬機的又一個優化技術.。Intel 的 x86 CPU 通常使用4Kb內存頁,當是經過配置,也能夠使用巨頁(huge page): (4MB on x86_32, 2MB on x86_64 and x86_32 PAE)
使用巨頁,KVM的虛擬機的頁表將使用更少的內存,並且將提高CPU的效率。最高情況下,可以提高20%的效率!
使用方法,需要三部:
mkdir /dev/hugepages
mount -t hugetlbfs hugetlbfs /dev/hugepages
#保留一些內存給巨頁 sysctl vm.nr_hugepages=2048 (使用 x86_64 系統時,這相當於從物理內存中保留了2048 x 2M = 4GB 的空間來給虛擬機使用)
#給 kvm 傳遞參數 hugepages qemu-kvm - qemu-kvm -mem-path /dev/hugepages
也可以在配置文件里加入:
<memoryBacking> <hugepages/> </memoryBacking>
驗證方式,當虛擬機正常啟動以后,在物理機里查看:
cat /proc/meminfo |grep -i hugepages
老外的一篇文檔,他使用的是libvirt方式,先讓libvirtd進程使用hugepages空間,然后再分配給虛擬機。
參考資料:
http://www.cnblogs.com/xusongwei/archive/2012/07/30/2615592.html
https://www.ibm.com/developerworks/cn/linux/l-cn-vt/
http://www.slideshare.net/HwanjuKim/3cpu-virtualization-and-scheduling
http://www.cse.iitb.ac.in/~puru/courses/autumn12/cs695/classes/kvm-overview.pdf
http://www.linux-kvm.com/content/using-ksm-kernel-samepage-merging-kvm
http://blog.csdn.net/summer_liuwei/article/details/6013255
http://blog.pchome.net/article/458429.html
http://blog.chinaunix.net/uid-20794164-id-3601787.html
虛擬化技術性能比較和分析,周斌,張瑩
http://wiki.qemu.org/images/c/c8/Cpu-models-and-libvirt-devconf-2014.pdf
http://frankdenneman.nl/2011/01/11/beating-a-dead-horse-using-cpu-affinity/
