KVM是必須使用硬件虛擬化輔助技術(如Intel VT-x、AMD-V)的Hypervisor,在cpu運行效率方面有硬件支持、其效率是比較高的;前端
在有Intel EPT特性支持的平臺上,內存虛擬化的效率也較高。後端
不過,KVM在I/O虛擬化方面,傳統的方式是使用QEMU純軟件的方式來模擬I/O設備,其效率不好。(性能和兼容性的博弈)網絡
QEMU模擬過程socket
在使用QEMU模塊I/O的狀況下,當客戶機中的設備驅動程序(Device Driver)發起I/O操做請求之時,KVM模塊(Module)中的I/O操做捕獲代碼會攔截I/O請求,而後在通過處理後將本次I/O請求。而後通過處理後將本次I/O請求的信息存放到I/O共享頁(sharing page),並通知用戶空間的QEMU程序。Qemu模擬程序獲取I/O操做的具體信息以後,交由硬件模擬代碼(EmulationCode)來模擬出本次的I/O操做,完成以後,將結果放回到I/O 共享頁,並通知KVM模塊中的I/O操做捕獲代碼。最後,由KVM模塊中的捕獲代碼讀取I/O共享頁中的操做結果,並把結果返回到客戶機中。固然,在這個操做過程當中客戶機做爲一個Qemu進程在等待I/O是也可能被阻塞。另外,當客戶機經過DMA(Direct Memory Access)訪問大塊I/O之時,QEMU模擬程序將不會把操做結果放到I/O共享頁中,而是經過內存映射的方式將結果直接寫到客戶機內存中區,而後經過KVM模塊告訴客戶機DMA操做已經完成。性能
virtio I/O半虛擬化磁盤操作系統
前端驅動(frondend,如virtio-blk、virtio-net)是在客戶機中存在的驅動程序模塊,然後端處理程序(backend)是在QEMU中實現的。命令行
在先後端定義了兩層來支持客戶機與QEMU之間的通訊。隊列
virtio層,在概念上,將前端驅動程序附加到後端程序。一個前端驅動程序可使用0個或多個隊列,具體數量取決於需求。(virtio-net 2個隊列,virtio-blk一個隊列)進程
虛擬隊列實際上被實現爲跨越客戶機操做系統和Hypervisor的銜接點,但該銜接點能夠經過任意方式實現。內存
virtio-ring實現了環形緩衝區(ring buffer),用於保存前端驅動和後端處理程序執行的信息,而且該環形緩衝區能夠一次性保存前端驅動的屢次請求,而且交由後端驅動去批量處理,最後實際調用宿主機中設備驅動實現物理上的I/O操做,這樣作就能夠根據約定實現批量處理而不是客戶機中每次I/O請求都須要處理一次,從而提升客戶機與Hypervisor信息交換的效率。
virtio、virtio_ring、virtio_pci等驅動程序提供了對virtio API的基本支持,是使用任何virtio前端驅動都必須使用的,並且他們的加載還有必定的順序,應該按照virtio、virtio_ring、virtio_pci的順序加載,而virtio_net、virtio_blk這樣的驅動能夠根據實際須要進行選擇性的編譯和加載。
virtio ballooning
氣球中的內存時能夠供宿主機使用的(但不能被客戶機訪問或使用),因此,當客戶機內存緊張,空餘內存很少的時候,能夠請求客戶機回收利用已分配給客戶機的部份內存,客戶機就會釋放其空下內存,此時若客戶機空閒內存不足,可能還會回收部分使用中的內存,可能會將部份內存換出到客戶機的交換分區(swap)中,從而是內存氣球充氣膨脹,進而是宿主機回收氣球中的內存用於其餘進程。反之,當客戶機內存不足時,也可讓客戶機的內存氣球壓縮,釋放出內存氣球中的部份內存,讓客戶機使用更多的內存。(真繞!)
KVM中ballooning的工做過程主要有以下步驟:
1) Hypervisor(即KVM)發送請求到客戶機操做系統讓其歸還必定數量的內存給Hypervisor
2) 客戶機操做系統中的virtio_balloon驅動接收到Hypervisor的請求。
3) virtio_balloon驅動使客戶機的內存氣球膨脹,氣球中的內存就不能被客戶機訪問。若是此時客戶機中的內存剩餘很少,而且不能讓內存氣球膨脹到足夠大以知足Hypervisor的請求,那麼virtio_balloon驅動也會盡量地提供內存使氣球膨脹,儘可能去知足Hypervisor的請求中的內存數量(即便不必定能徹底知足)。
4) 客戶機操做系統歸還氣球中的內存給Hypervisor
5) Hypervisor能夠將氣球中得來的內存分配到任何須要的地方
6) 即便從氣球中獲得的內存沒有處於使用中,Hypervisor也能夠將內存返還到客戶機中,這個過程爲:Hypervisor發請求到客戶機的virtio_balloon驅動;這個請求是客戶機操做系統壓縮內存氣球;在氣球中的內存被釋放出來,從新由客戶機訪問和使用。
vhost_net後端驅動
virtio在宿主機中的後端處理程序(backend)通常是由用戶空間的QEMU提供的,然而,若是對於網絡IO請求的後端處理可以在內核空間開完成,則效率會更高提升網絡吞吐量和減小網絡延遲。
vhost-net的驅動模塊,做爲一個內核級別的後端處理驅動,將virtio-net的後端處理任務放到內核空間中執行,從而提升效率。
「使用網橋模式」
-net tap,[,vnet_hdr=on|off][,vhost=on|off][,vhostfd=h][,vhostforce=on|off]
通常來講,使用vhost-net做爲後端處理程序能夠提升網絡的性能。不過,對於一些使用vhost-net做爲後端的網絡負載類型,可能使其性能不升反降。特別是從宿主機到其客戶機之間的UDP流量,若是客戶及處理接受數據的速度比宿主機發送的速度要慢,這是就容易出現性能降低。在這種狀況下,使用vhost-net將會是UDPsocket的接受緩衝區更快的溢出,從而致使更多的數據包丟失。所以在這種狀況下不使用vhost-net,讓傳輸速度稍微慢一點,反而會提升總體的性能。
使用qemu-kvm命令行時,加上「vhost=off」
<interface type="network">
<model type="virtio"/>
<driver name="qemu"/>
</interface>
virtio_blk 驅動使用virito API爲客戶機提供了一個高效訪問塊設備I/O的方法。
在QEMU/KVM中對塊設備使用virito,須要在兩方面進行配置:客戶機中的前端驅動模塊virito_blk和宿主機中的QEMU提供後端處理程序。