1. 程式人生 > >虛擬化的發展歷程和實現方式

虛擬化的發展歷程和實現方式

同時 方法 發展歷程 note 沒有 avi cati 當我 訪問

前言

現在市場上最常見的虛擬化軟件有VMWare workstation(VMWare)、VirtualBox(Oracle)、Hyper-V(Microsoft)、KVM(Redhat)、Xen等,這些軟件統稱之為VMM(Virtual Machine Monitor),使用不同的虛擬化實現。而這些虛擬化實現的方式可以分為全虛擬化、半虛擬化、硬件虛擬化等,本篇主要是理解這些虛擬化實現的原理。

虛擬化

虛擬化的誕生與實現
1961年 — IBM709機實現了分時系統,將CPU占用切分為多個極短(1/100sec)時間片,每一個時間片都執行著不同的任務。通過對這些時間片的輪詢,這樣就可以將一個CPU虛擬化或者偽裝成為多個CPU,並且讓每一顆虛擬CPU看起來都是在同時運行,這就是虛擬機的雛形。後來的system360機都支持分時系統。
1972年

— IBM正式將system370機的分時系統命名為虛擬機。
1990年 — IBM推出的system390機支持邏輯分區,即將一個cpu分為若幹份(最多10份),而且每份cpu都是獨立的,也就是一個物理cpu可以邏輯的分為10個cpu。

直到IBM將分時系統開源後,個人PC終於臨來了虛擬化的開端,後來才有了上述的虛擬機軟件的發展。所以至今為止仍然有一部分虛擬機軟件應用來了分時系統作為虛擬化的基礎實現。

虛擬化的目的:使用邏輯來表示資源,從而擺脫物理限制的約束。提高物理資源的利用率。
虛擬化的原理:在OS中加入一個虛擬化層(VMM),虛擬化層可以對下層(HostOS)硬件資源(物理CPU、內存、磁盤、網卡、顯卡等)進行封裝、隔離,抽象為另一種形式的邏輯資源,再提供給上層(GuestOS)使用。所以你可以理解VMM其實就是聯系HostOS和GuestOS的一個中間件,當然虛擬化可以將一份資源抽象為多份,也可以將多份資源抽象為一份。

通過虛擬化技術實現的虛擬機一般被稱之為GuestOS(客戶),而作為GuestOS載體的物理主機稱之為HostOS(宿主)。

虛擬機Virtual Machine

  • 由VMM提供的高效(>80%)、獨立的計算機系統
  • 擁有自己的虛擬硬件(CPU、內存、網絡設備、存儲設備)
  • 對於上層軟件,虛擬機就是真實的機器
  • Virtual Machine Monitor

滿足上面幾個條件的OS就是虛擬機。
技術分享

VM的特性
同質:VM的本質與物理機的本質相同,e.g. CPU的ISA(指令集架構 Instruction Set Architecture)相同
高效:性能與物理機接近,在VM上執行的大多數指令應該有權限和能力直接在硬件上執行,只有少數的敏感指令由VMM來處理。對於VM的性能效率在上一篇
資源可控:VMM對物理機和虛擬機的資源都是絕對可控的
Redhat曾經測試過一些應用服務在虛擬機上運行的效率。一部分的報告如下:

IBM DB2SAPORACLEJAVALAMP
VM=HOST * 90% VM=HOST * 90% VM=HOST * 90% VM=HOST * 94% VM=HOST * 138%

NOTE:LAMP在VM上運行的效率之所以能夠提高是因為將Apache、PHP/Python、MySQL 3個應用服務拆分到3個不同的VM中運行。
技術分享

虛擬化的分類

在虛擬化發展的早期主要以全虛擬化半虛擬化兩大流派為主,兩者各有優缺點。如果能適當的將其應用不同的環境中,就能充分的發揮兩者的特性以獲得更高的收益。隨著這兩大流派的分歧和競爭愈演愈烈,由Intel領銜的硬件廠商也紛紛加入到虛擬化的浪潮中,開啟了(大航海時代)硬件虛擬化的時代,從此全虛擬化和半虛擬化前進的道路逐漸有了靠攏的趨勢。再到後來的 第二代的內存虛擬化第三代的總線虛擬化 的出現和興起,當下虛擬化市場已經不再以單純賣賣虛擬化軟件為主要盈利手段,而是將虛擬化技術整合在更大、更完善的虛擬化平臺解決方案中。其中包括Redhat的RHEV、VMWare的vSphere等。

x86 CPU架構與虛擬化的關系

在理解各種虛擬化的實現之前,首先需要了解一般x86 CPU的架構。

技術分享

註意:CPU為了保證程序代碼執行的安全性、多用戶的獨立性、保護OS的正常運行,提出了CPU執行狀態的概念。這樣能夠限制不同程序之間的訪問能力,避免一個程序獲取另一個程序的內存數據造成數據混亂,同時也避免了程序錯誤的操作物理硬件。一般CPU都會劃分為 用戶態內核態 ,x86的CPU架構更是細分為了Ring3~0四種狀態。

Ring3 用戶態(User Mode):運行在用戶態的程序代碼需要受到CPU的檢查,用戶態程序代碼只能訪問 內存頁表項中 規定能被用戶態程序代碼訪問的頁面虛擬地址(受限的內存訪問),而且還只能訪問 TSS中的I/O Permission Bitmap 中規定能被用戶態程序代碼訪問的端口。甚至不能直接訪問外圍硬件設備、不能搶占CPU。所有的應用程序(Application)都運行在用戶態上。——當運行在用戶態的Application需要調用只能被核心態代碼直接訪問的硬件設備時,CPU會通過特別的接口去調用核心態的代碼,以此來實現Application對硬件設備的調用。 如果用戶態的Application直接調用硬件設備時,就會被Host OS捕捉到並觸發異常,彈出警告窗口。

Ring0 核心態(Kernel Mode):是Host OS Kernel運行的模式,運行在核心態的代碼可以無限制的對系統內存、設備驅動程序、網卡接口、顯卡接口等外圍硬件設備進行訪問。只有Host OS能夠無限制的訪問磁盤、鍵盤等外圍硬件設備的數據,但是首先需要在Host OS上安裝驅動程序。

技術分享

虛擬化實現圖

技術分享

粗略而言,GuestOS和VMM都屬於運行在Ring3上的應用程序,GuestOS操作硬件設備時並執行操作指令時,VMM會將該操作指令監控、捕獲、檢測後將指令傳遞給HostOS,HostOS會將GuestOS發出的運行於用戶態的操作指令模擬為核心態指令。
註意:當上述的流程是非常簡略的,在與全虛擬化和半虛擬化的實現過程集合時,就會變得非常復雜。

全虛擬化 Full virtualization

GuestOS可以直接在全虛擬化VMM上運行而不需要對GuestOS本身的核心代碼做任何修改,全虛擬化的GuestOS具有完全的物理機特性。既VMM會為GuestOS抽象模擬出它所需要的包括CPU、磁盤、內存、網卡、顯卡等抽象硬件資源,所以全虛擬化的GuestOS並不會知道自己其實是一臺虛擬機。

結合上述的虛擬化實現圖來看:當我們使用GuestOS的時候,不可避免的會調用GuestOS中的 虛擬設備驅動程序核心調度程序 來操作硬件設備。與HostOS的不同在於,HostOS運行在CPU的核心態中,這就表示HostOS可以直接對硬件設備進行操作。但GuestOS作為一個運行在CPU用戶態中應用程序,不能夠直接的操作硬件設備。為了解決這個問題,VMM引用了兩個機制——特權解除 & 陷入模擬

特權解除:也稱之為 翻譯,當GuestOS需要調用運行在核心態的指令時,VMM就會動態的將核心態指令捕獲並調用若幹運行在非核心態的指令來模擬出期望得到的效果(GuestOS和VMM是運行在用戶態上的應用程序),從而將核心態的特權解除。解除了核心態的特權後,就能夠在GuestOS中執行大部分的核心態指令了。但是,這仍然不能完美的解決問題。因為在一個OS的指令集中還存在著一種敏感指令(可能是內核態,也可能是用戶態)。此時就需要陷入模擬的實現。

陷入模擬:無論是HostOS還是GuestOS,只要是一個OS都必然會存在有敏感指令(reboot、shutdown等)。試想如果我們希望將GuestOS重啟,並在GuestOS中執行了reboot指令,但是卻將HostOS給重啟了,這將會非常糟糕。VMM的陷入模擬機制就是為了解決這個問題。e.g. 在GuestOS中執行了敏感指令reboot時,VMM首先會將敏感指令reboot捕獲、檢測並判定其為敏感指令。此時VMM就會陷入模擬,將敏感指令reboot模擬成一個只針對GuestOS進行操作的、非敏感的、並且運行在非核心態上的"reboot"指令,最後CPU執行虛擬機的重啟操作。

由於全虛擬化VMM會頻繁的捕獲這些核心態的和敏感的指令,將這些指令進行轉換之後,再交給CPU執行。所以 經過了兩重轉換,導致其效率會比半虛擬化更低,但全虛擬化VMM應用程序的好處在於其不需要對GuestOS的核心源碼做修改,所以全虛擬化的VMM可以安裝絕大部分的OS(暫時來說只有已Linux、open soralis、BSD等幾種OS開源了內核代碼)。典型的全虛擬化軟件有 —— VMWare、Hyper-V、KVM-x86(復雜指令集)。

全虛擬化的兩種實現方式
1). 基於二進制翻譯的全虛擬化
2). 基於掃描和修補的全虛擬化

半虛擬化 Paravirtualization

半虛擬化是需要GuestOS協助的虛擬化。因為在半虛擬化VVMM中運行的GuestOS,都需要將其內核源碼進行都進過了特別的修改。半虛擬化VMM在處理敏感指令和內核態指令的流程上相對更簡單一些。在半虛擬化VMM上運行的GuestOS都需要修改內核代碼,主要是修改GuestOS指令集中的敏感指令和核心態指令。讓HostOS在捕抓到沒有經過半虛擬化VMM模擬和翻譯處理的GuestOS內核態指令或敏感指令時,HostOS也能夠準確的判斷出該指令是否屬於GuestOS(GuestOS知道自己是虛擬機)。這樣就可以高效的避免了上述問題。典型的半虛擬化軟件有——Xen、KVM-PowerPC(簡易指令集)

半虛擬化除了修改內核外還有另外一種實現方法——在每一個GuestOS中安裝半虛擬化軟件,e.g. VMTools、RHEVTools。

註意:若使用KVM運行Windows時,一定要安裝半虛擬化驅動Tools,否則無法工作。現在主流的半虛擬化驅動是由IBM和redhat聯合開發一個通用半虛擬機驅動virtio 。

硬件輔助虛擬化 HVM

技術分享
2005年 — Intel提出並開發了由CPU直接支持的虛擬化技術。這種虛擬化技術引入新的CPU運行模式和新的指令集,使得VMM和GuestOS運行於不同的模式下(VMM=Root Mode;GuestOS=Non-Root Mode),GuestOS運行於受控模式,原來的一些敏感指令在受控模式下會全部陷入VMM,由VMM來實現模擬,這樣就解決了部分非內核態敏感指令的陷入——模擬難題,而且模式切換時上下文的保存恢復由硬件來完成,這樣就大大提高了陷入——模擬時上下文切換的效率 。該技術的引入使x86 CPU可以很容易地實現完全虛擬化。故皆被幾乎所有之前分歧的各大流派所采用,包括KVM-x86,VMWare ESX Server 3,Xen 3.0 。

HVM的分類
1). Intel –> VT-X
2). AMD –> AMD-V

內存虛擬化

原來的GuestOS使用的是虛擬內存,不可以缺少虛擬內存到物理內存的翻譯,影響了虛擬機的效率。後來Intel EPT AMD RVI表示支持內存虛擬化。

內存虛擬化的映射實現*

A –> 虛擬地址(VA),指GuestOS提供給其應用程序使用的線性地址空間。
B –> 物理地址(PA),經VMM抽象的,虛擬機看到的偽物理地址
C –> 機器地址(MA),真是的機器物理地址,即地址總線上出現的地址信號
內存地址的映射關系:
GuestOS:PA = f(VA) #GuestOS維護著一套頁表,負責VA到PA的映射
VMM:MA = g(PA) #VMM維護著一套頁表,負責PA到MA的映射
通過轉換方法實現了從虛擬地址到機器地址的映射。實際運行時,用戶程序訪問VA1,經過GuestOS的頁表轉換得到PA1,再由VMM介入並使用VMM的頁表將PA1轉換為MA1 。

總線虛擬化

分類
1). Intel –> VT/d

2). AMD –> iommu
總線虛擬化可以實現將一塊網卡分給若幹個GuestOS使用,每個虛擬機1/N,性能高,接近真機。
從軟件的角度出發,IO設備就是一堆狀態寄存器,控制寄存器,中斷並與其交互
主要的虛擬化方式:設備接口完全模擬、前端-後端模擬(Xen) ?
直接劃分:直接把物理設備劃分給Guest OS,無須經過VMM。Intel VT-d

內存虛擬化和總線虛擬化進一步的拉近了GuestOS和HostOS的運行性能。

虛擬化的發展歷程和實現方式