虚拟化原理介绍

什么是虚拟化?
  一台PC机的组成包括:Keyboard(键盘)、Monitor(显示器)、CPU、RAM、I/O(Disk,Network),这是基本的五大部件。
  虚拟化就是在这些基础物理设备上运行多个OS。

虚拟化面临的重要问题概述:CPU、RAM、I/O的模拟。
 CPU模拟:
  (1) 所有OS设计时都认为Kernel是可以控制所有硬件,并可运行CPU的特权指令,即Kernel运行于CPU的Ring0上。
  (2) 多个OS无法同时直接运行于硬件层之上,它们必须运行在Hypervisor层(下文称:Host)上;就如同不安装操作系统,
   就不能安装VMware,没有VMware就无法让虚拟机(下文称:Guest)运行起来一样。那问题来了,若GuestOS必须
   运行在CPU的Ring0上,Host运行在哪里?
  (3) OS设计时它认为自己是可以控制所有硬件资源的,那GuestOS之间不就可以相互影响了吗?Guest1要关机,若
      它直接执行CPU的特权指令关机,那它应该可以关闭整个物理机器,这不是虚拟化所希望的。

  这些问题给CPU虚拟化带来了诸多问题, 但实际上Host一定是真正能执行CPU的特权指令的,Guest运行起来后,它
 实际控制的CPU是通过软件模拟的CPU,实际上任何物理硬件都是通过集成电路进行运算,通过微代码向外提供输出结果
 的接口,只有通过软件模拟出这些接口就可以模拟硬件.
  BT技术: 
    BinaryTranslation(二进制翻译)技术,它可以让Guest在发起特权指令时,直接将其翻译为Host的系统调用,
   以便加速Guest的执行性能.
  BT技术出现是因为Guest用户空间的APP要进行特权操作时,Guest上的APP需要先将请求发给Guest的Kernel,
  Guest的Kernel经翻译转换发给模拟CPU,模拟CPU在将其转换为Host的系统调用,再发给Host的Kernel,它再
  进行翻译转换后给物理CPU执行.最后返回,这使得GuestOS的执行性能不高.
    模拟CPU 和 虚拟CPU:
   》模拟CPU:是完整虚拟,即模拟出CPU的环0,环1,环2,环3;这通常在底层硬件与虚拟环境的硬件不同时
    采用模拟CPU的方式。
   》虚拟CPU:仅模拟CPU的环0, Guest的用户空间中的APP可直接运行在物理CPU的环3上,仅环0上的特权
    指令进行翻译.这是Guest的硬件环境与底层硬件环境一致时用。

  完全虚拟化 和 半虚拟化:
   》完全虚拟化(Full-Virtulization): 
    即Guest不知道自己是运行在虚拟化环境中,它一直都认为自己是可以控制全部的硬件资源.
    因此需要将GuestOS对特权指令的操作都进行翻译后,由Host带为执行。
    VMware的BT技术 和 AMD CPU的AMD-v、Intel的VT-x这两种HVM(硬件虚拟化)技术实际
    上都是完全虚拟化,因为它们都是帮助Host高效完成特权指令翻译的技术。
 注:
  AMD-v 和 VT-x实现了将原先只有4环的CPU扩展为5环,并让Host运行在-1环上,腾出环0给Guest用,
  这样Guest就认为自己是运行在环0上,并且可直接执行特权指令,但实际上,Guest调用环0上的特权指令时,
  CPU会直接将其翻译为真实的特权指令并激活Host的内核来调用环-1来执行特权指令,这进一步缩短了
  翻译流程。

  Memory虚拟化:
  (1) 在物理机中,内存的使用是经过虚拟化后,提供给物理机上运行的APP用的。
  (2) 在物理机中,APP看到的内存是:
    虚拟线性地址空间,即APP认为自己使用的是全部的物理内存,从0-1024(假设内存为1G)内核看到的内存是:
   真实物理地址空间
  (3) 由于物理机的内存已经被虚拟化过了, Guest访问物理内存就需要再次被虚拟一层。
   注:TLB: 转换后页面缓存 
   Host上的APP访问内存的流程:
    APP-->发送访问线性地址:10page的数据-->CPU-->将10page的线性地址转给MMU-->
    查询线性与物理地址映射表-->缓存映射关系到TLB,并读取物理地址中的数据-->返回。
   GuestOS上的APP访问内存的流程:
    Shadow Page Table的方式:
     注: 假设将Guest的APP访问的虚拟线程地址称为:GVA.
     将Guest虚拟机所获得的虚拟物理内存地址称为:GPA
      Guest-APP-->发送访问线性地址(GVA):10page的数据-->虚拟CPU-->
      将其转给虚拟MMU-->查询并缓存映射到虚拟TLB-->
      GPA的访问请求被发给Host-->
      但GPA并非Host的虚拟线性地址,又非真实物理地址,因此无法由真实CPU处理-->
      Host上不得不采用软件模拟来完成将GPA转换为真实物理内存的物理地址,
      此方式叫 Shadow page table(影子页表)最终获得物理内存中的数据,并返回给Guest.

Intel的EPT(Extended Page Table:扩展页表) 和 AMD的NPT(Nested Page Table:嵌入页表)技术
》MMU虚拟化 和 TLB虚拟化
  注: TLB虚拟化: 由于GuestA和GuestB都被分配了1G的内存,GuestA和GuestB将具有相同的内存地址,
 但GuestA和GuestB它们实际映射到Host上的物理内存的地址段肯定是不同的。但GuestA
 访问它的10page的数据若被缓存在TLB中,GuestB到CPU执行时,它恰巧也要访问它的10page的数据
 那TLB中缓存的条目肯定会对GuestB造成干扰,导致访问错误,因此只能将TLB清空,即GuestB到CPU
 上执行时,TLB是空的,因此CPU只能再通过MMU查映射关系,缓存TLB再访问数据。这导致TLB成了摆设
  没有起到提高访问物理内存效率的作用。这才出现了TLB的虚拟化, 而TLB的虚拟化将原先的只有两个
 字段缓存的TLB改成缓存三个字段: 一个GuestOS标识(实际为:VPID),一个GVA,一个HPA(Host中真实物理地址)。
 Guest-APP-->发生访问线性地址(GVA): 10page的数据--->这时访问请求被同时发送了两份,并同时分别走了以下路线
 路线1-->虚拟CPU-->虚拟MMU-->虚拟TLB-->完成.
 路线2-->EPT/NPT硬件实现的MMU-->EPT/NPT实现的TLB-->获取真实物理地址中的数据-->返回给Guest.
  这样做后,即没有改变GuestOS访问内存的过程,同时提高了GuestOS访问内存的效率。
注:
  VPID(VirtualProcessorIdentifiers:虚拟处理器标识) :它是在硬件上对TLB资源管理的优化,它给每个TLB项新增
 了一个标识.用于不同vCPU的地址空间,从而能够区分开Hypervisor和不同处理器的TLB。硬件区分了不同TLB
   项分属于不同的vCPU,因而避免了每次VM调出和调入时,让全部的TLB失效这一动作,加速了VM切换和运行的效率。
   查看EPT 和 VPID
  grep -E 'ept|vpid' /proc/cpuinfo
  或 
  cat /sys/module/kvm_intel/parameters/{ept,vpid}
   关闭和开启EPT 和 VPID的方法:
    modprobe kvm_intel ept=0,vpid=0 && rmmod kvm_intel #关闭EPT和VPID.
    modprobe kvm_intel ept=1,vpid=1 #开启EPT和VPID.


I/O虚拟化:
  (1) 外存设备虚拟化
    磁盘、光驱、U盘
  (2) 网络设备虚拟化
    网卡
  (3) 输入设备 : 
    它的虚拟化采用角点当前被谁捕获来模拟的,若当前被虚拟机捕获,则会动态将模拟键盘或鼠标与物理设备关联.
    ps/2、USB
  (4) 显示设备 : 它不能被模拟。
    VGA

 I/O虚拟化的三种技术:
 【注: 这三种技术只针对存储和网络,其I/O设备的模拟不采用这些技术。】
 》模拟 : 如VMware拿一个文件做为VM的磁盘,这就是模拟。
 》半虚拟化:
  模拟的过程:
    Guest-APP去访问I/O设备,如网卡,Guest-Kernel需要先调用虚拟网卡的驱动-->虚拟网卡驱动将数据
   转发给虚拟网卡-->虚拟网卡再转给Hypervisor上模拟的网卡进程-->该网卡进程再将数据放入IO Stack(IO栈)中
   等待真实网卡驱动将其转给物理网卡并由其将数据转发出去。
  半虚拟化的过程:
    Guest-APP去访问I/O设备,如网卡,但此时GuestOS明确知道自己不能直接访问到物理网卡,因此,
   直接将数据转给前端设备(它类似一个转发器,但对GuestOS中的用户看来它是一个网卡设备)-->
   前端设备直接与Hypervisor上的网卡进程通信-->网卡进程将数据转到IO Stack中-->
   物理机驱动将其转发给物理网卡。
  注:
     前端设备(IO frontend):在Guest端省去了Guest虚拟网卡驱动的步骤。
     后端设备(IO backend):在Hypervisor端从虚拟网卡进程到物理网卡称为后端设备。
 》I/O透传:
  假如规划中该主机上需要运行4台虚拟机,该主机上安装了6块盘,6块网卡,物理机磁盘和网卡都使用两个,
 剩余的都给虚拟机使用,那完全可以给每个虚拟机分一个物理磁盘和一个物理网卡,这样其性能可几乎
 接近于硬件访问,但这需要Hypervisor中的设备管理器来分配。

x86平台上DMA(直接内存访问)是集中共享式管理的
  假如当前Hypervisor管理着4块网卡,现在GuestA和GuestB要发送数据到网卡上,
 GuestA和GuestB都需要借助DMA来代其完成,但DMA是共享式管理,它仅仅负责接收
   Kernel发来的命令然后,根据指示将指定内存地址中的数据发送到指定IO设备,如网卡,
   或将网卡上收到的数据存入到指定的内存地址中。问题是Guest通过复杂的kernel调用
   过程完成了DMA代其发送数据包到网卡,但GuestOS并不知道DMA将数据包发到那个网卡
  上了,更没有人知道回应的包到网卡后,应该转发给那个GuestOS.
  注: 
  DMA:它的作用是帮助Kernel完成一些需要长时间等待的任务,如:写数据到磁盘,
 从磁盘中读数据到内存,将网卡上收到的数据读到内存等; 这对提供Kernel的执行
 效率是非常有帮助的。

IO设备:
  每个IO设备上都有控制器,并且每个IO设备的控制器上都有寄存器且都有相应的端口地址。
  IOMMU: IO内存地址管理单元
  它的作用是自动将IO总线与相应的IO端口关联的设备。
  若需要将某块网卡绑定给某GuestOS单独使用,就需要在Hypervisor级别来控制对I/O端口的调用
 就只能接受该GuestOS的调用了,而它的实现就需要借助DMA中实现IOMMU来完成。而Intel的VT-d
 就是这样一种技术,它在DMA中实现了IOMMU,并自动来完成IO总线与IO端口的映射关联。
   IOMMU的映射是完成将物理IO设备绑定给GuestOS的第一步,接着还需完成将物理IO设备的中断信号
   也要映射给该GuestOS,要知道物理设备在实现中断映射通常采用中断控制器 或 DMA等方式实现,而采用DMA方式
   则需要DMA必须能够访问全部的物理内存,因为DMA需要将IO设备的寄存器中的数据搬到指定的内存地址空间
   或反过来;而若将物理硬件绑定给GuestOS,则DMA就需要访问GuestOS的全部物理内存,但实际上GuestOS
   的内存是虚拟的,这就需要经过复杂的转换后才能访问到其对应的物理内存地址空间,这也进一步加大了
   中断信号与GuestOS的映射;而这还是完成虚拟机绑定硬件的第二步。
   最后一步是完成IO设备缓冲区与GuestOS的映射,这里必须知道缓冲区一定是物理内存中的一段空间,如何让
   虚拟机的内核知道这是自己所管理的物理IO设备的IO缓冲区?;而这一切Intel的VT-d都帮我们实现了。

Intel的VT-d
  简单来说 VT-d 是一种基于北桥的硬件辅助虚拟化技术。

Intel的硬件辅助虚拟化技术:
  CPU: vt-x, EPT, tagged-TLB
  IO: vt-d,SR-IOV:单根设备虚拟化协议, VMDq
  这些技术详细分为三类:
    第一类: 跟处理器相关: VT-x, EPT, tagged-TLB
    第二类: 跟芯片相关: vt-d
    第三类: 跟IO输入输出相关: VMDq 和 SR-IOV

  IO虚拟化技术: QEMU(法国天才程序员开发) 、virtio(澳大利亚天才程序员开发)
  KVM和Xen都需要借助以上两种虚拟化技术实现IO虚拟化。

虚拟化技术分类:
  (1) 模拟:【特点:虚拟硬件环境与底层硬件环境无关.】
    著名的模拟器: PearPC, Bochs, QEMU
  (2) 完全虚拟化: 【特点: 虚拟硬件环境与底层硬件环境必须一致。】
    在完全虚拟化中通常采用两种加速技术:
    BT : 二进制翻译加速技术
    HVM: 基于硬件的虚拟化
    知名的产品:
      VMware Workstation, VMware Server, Parallels Disktop(iMac上用), KVM, Xen(HVM)
  (3) 半虚拟化:【同样要求虚拟硬件环境与底层硬件环境必须保持一致】
    知名的开源产品: xen, uml(user-mode linux)
  (4) OS级别的虚拟化(容器):
    OpenVZ, LXC(LinuX Container), libcontainer, Virtuozzo, Linux V Servers
    Solaris Containers
    FressBSD jails
  (5) 库虚拟化:
    wine

网卡虚拟化-------桥接
     通过让网卡工作在混杂模式下,将收到的所有包都接收进来,最后将根据MAC来将数据包发给真实网卡和虚拟网卡。

  

CPU虚拟化------Ring0
  在x86架构中CPU为了保护特权指令的运行,提供了指令的4个不同Privilege特权级别,术语称
 为Ring,从Ring 0~Ring 3。Ring 0的优先级最高,可运行所有特权指令,Ring 3最低。
 而对于一个OS来说它必须是运行在Ring0上的,当然对于GuestOS来说也是如此,因此对于VMM
 就必须模拟让GuestOS认为自己是运行在Ring0上;这样当GuestOS向CPU发送一个特权指令时,
   VMM(虚拟机监控器,或叫Hypervisior)必须监测到并调用BT捕获这个特权指令,在BT进程内部
   将特权指令转换为非特权指令,然后,由VMM向宿主OS发起请求进行处理。
   BT(Binary Translation): 二进制翻译器,它的作用是将GuestOS发出的特权指令转换为非特权指令,
   并交由宿主OS执行。它最早是由VMware采用的一种动态翻译技术,它将捕获的GuestOS发出的特权
   指令直接在其进程内部进行转换翻译,最终达到VMM所允许执行的指令,再交由宿主OS执行。

  

    由于VMM并不是所有特权指令都可捕获,且有些特权指令执行失败后,并不会返回给GuestOS
 任何信息,还有在中断虚拟化带来的诸多问题VMM都不能很好的解决,因此,后来Intel和AMD分别
    通过硬件实现了直接由CPU自身来实现虚拟化,即VT-x(intel) 和 AMD-V;这两种解决方案的原理是
   一样的,在原先4个CPU等级执行环的基础上新增量一个Ring-1的环,将所有CPU的特权指令放到Ring-1中,
   并让宿主机的Kernel可运行于Ring-1中,这就将Ring0空闲出来,接着让GuestOS的Kernel可运行在
   Ring0中,GuestOS执行的特性指令直接有CPU进行翻译并交给Ring-1中 执行,这就是VT-X 和 AMD-V
   实现的硬件虚拟化。


内存虚拟化
 无内存虚拟化:
   在没有虚拟化时,GuestOS要请求内存空间时,它需要将请求的线性地址(虚拟地址:Virtual Address),
  经MMU转为Physical Address最后由VMM将GuestOS的PA转交给真机的MMU,并由真机的MMU转为
  真机的PA,最后将数据存入真机的物理内存空间中。
 有内存虚拟化:
   GuestOS依然按它必须的方式将VA---->MMU---->PA,这个过程在GuestOS内部还是要走的,因为这是OS的
  固定运行机制;而在内存虚拟化这种方式下,真机上被虚拟出了一个MMU,将GuestOS的VA(虚拟地址)又转了
  一份给真机虚拟的MMU,由真机虚拟的MMU直接将GuestOS的VA转为真机的PA,而真机的PA与GuestOS的
  PA之间是建立了一种透明的映射关系,就如:GuestOS的PA2就对应真机的PA10一样。

    

    真机上虚拟的MMU,又称为影子MMU,它是对MMU芯片的虚拟化;Intel推出了一个EPT
 (扩展页表技术)而AMD推出了一个NPT(嵌套页表技术),他俩都是影子MMU的硬件虚拟化解决方案;
 它们实现的方式是:原先影子MMU实现是这样的,假如现在有A和B两个GuestOS,CPU是轮流分别
 处理它们的请求当CPU执行到A的时候,会将A请求的VA(Virtual Address)经影子MMU转换为真机的
 PA(Physical Address),并缓存在一个叫TLB的硬件芯片中存储;当GuestOS A使用完本次的CPU时间片后,
 CPU需要将A切到后台,将B切到前台执行,但为了防止B在执行过程中误用A缓存在TLB中的结果,故必须
 将其清空;当GuestOS A再次被调入前台执行时,发现自己的TLB被清空了,因此它会再次向影子MMU
 发出内存空间的请求, 经转换后在经结果缓存在TLB中,这时B的TLB缓存已经被清空了,这使得TLB缓存
 目的变的没有意义了。然而,EPT和NPT他们则通过在TLB中为每个GuestOS加入一个标记位,来区分
 各自的缓存结果,这样每次GuestOS切换回来后,直接在TLB中找到自己的标记就可以获取MMU的转换结果。

  

内存虚拟化的硬件解决方案:
  Intel 和AMD分别通过EPT(Extended Page Tables)和 NPT(Nested Page Tables)为虚拟化应用提升影子MMU的性能,
 并通过标记(tagged)TLB来避免虚拟机切换时频繁清写(flush)TLB以提高TLB缓存的命中率。

提升VM访问PCI和PCIe硬件设备的硬件虚拟化解决方案:
  Intel VT-d(Virtualization Technology for Directed I/O) 和 AMD Vi(也叫IOMMU) :
    深入了解VT-d和VT-x可参考: http://virtual.51cto.com/art/201102/245920.htm
   PCI硬件设备对VT-d技术的支持与否,决定了VM是否可独占使用该物理设备.并且这种使用
   几乎是不需要Hypervisor参与的。但是要真正实现VM直接使用物理设备,还需要中断重映射
   (Interrupt Remapping) 和DMA虚拟化(其中DMAR的核心芯片就是IOMMU) 的支持.

    

DMAR(DMA remapping): 
  它是Intel为支持虚拟化而设计的I/O虚拟化技术,它可简单理解为替代软件实现的影子页表,但真正执行
 将GuestOS的虚拟内存地址转换为宿主机的物理地址的硬件芯片是IOMMU。DMAR出现的原因是 
 DMA只能访问内存中的低地址空间,而且必须是连续的,这对虚拟化来说很难实现,因此Intel才在其CPU
 重新实现了DMA,让虚拟机能自由的访问内存中任意地址空间,且可不连续。

  

  IOMMA不仅将DMA地址虚拟化,还起到隔离、保护等作用,如下图所示意,详细请参阅Intel Virtualization Technology for Directed I/O

  

  #深入理解DMAR和IRQ虚拟化参考,由于本人理解有限,这部分是引用http://virtual.51cto.com/art/201102/245920.htm
  这篇博文的,仅作参考:
  传统的IOMMUs(I/O memory management units,I/O内存管理单元)提供了一种集中的方式管理所有的DMA——
   除了传统的内部DMA,还包括如AGP GART、TPT、RDMA over TCP/IP等这些特别的DMA,它通过在内存地址范围
   来区别设备,因此容易实现,却不容易实现DMA隔离,因此VT-d通过更新设计的IOMMU架构, 实现了多个DMA
   保护区域的存在,最终实现了DMA虚拟化。这个技术也叫做DMA Remapping。

    

   I/O设备会产生非常多的中断请求,I/O虚拟化必须正确地分离这些请求,并路由到不同的虚拟机上。
传统设备的中断请求可以具有两种方式:一种 将通过I/O中断控制器路由,一种是通过DMA写请求直接
发送出去的MSI(message signaled interrupts,消息中断),由于需要在DMA请求内嵌入目标
内存地址,因此这个架构须要完全访问所有的内存地址,并不能实现中断隔离。
      VT-d实现的中断重映射(interrupt-remapping)架构通过重新定义MSI的格式来解决这个问题,
新的MSI仍然是一个 DMA写请求的形式,不过并不嵌入目标内存地址,取而代之的是一个消息ID,
通过维护一个表结构,硬件可以通过不同的消息ID辨认不同的虚拟机区域。 VT-d实现的中断重映射
可以支持所有的I/O源,包括IOAPICs,以及所有的中断类型,如通常的MSI以及扩展的MSI-X。
VT-d进行的改动还有很多,如硬件缓冲、地址翻译等,通过这些种种措施,VT-d实现了北桥芯片
级别的I/O设备虚拟化。VT-d最终体现到虚拟化模型上的就是新增加了两种设备虚拟化方式:

   

    左边是传统的I/O模拟虚拟化,右边是直接I/O设备分配
    直接I/O设备分配:
    虚拟机直接分配物理I/O设 备给虚拟机,这个模型下,虚拟机内部的驱动程序
  直接和硬件设备直接通信,只需要经过少量,或者不经过VMM的管理。为了系统的健壮性,需要硬件的
  虚拟化支 持,以隔离和保护硬件资源只给指定的虚拟机使用,硬件同时还需要具备多个I/O容器分区来
  同时为多个虚拟机服务,这个模型几乎完全消除了在VMM中运行驱 动程序的需求。例如CPU,虽然
  CPU不算是通常意义的I/O设备——不过它确实就是通过这种方式分配给虚拟机,当然CPU的资源还处在
  VMM的管理之 下。
 I/O设备共享:
    这个模型是I/O分配模型的一个扩展,对硬件具有很高的要求,需要设备支持多个功能接口,
  每个接口可以单独分配给一个虚拟机,这个模型无疑可以提供非常高的虚拟化性能表现。
  运用VT-d技术,虚拟机得以使用直接I/O设备分配方式或者I/O设备共享方式来代替传统的设备模拟/额外设备
  接口方式,从而大大提升了虚拟化的I/O性能。

 

虚拟化的三大分类:

1. Full-Virtualization 完全虚拟化 
  【CPU不支持硬件虚拟化技术:模拟特权】
  【CPU支持硬件虚拟化,VMM运行Ring-1,而GuestOS运行在Ring0,
    此为硬件辅助的虚拟化:Hardware Asistant VM】

 完全虚拟化缺点:
  GuestOS的操作必须先通过System Call转给宿主OS最终将结果,经过多道工序后返回给GuestOS。
  如:GuestOS向外发包时,它先将包封装后发给VMM,有VMM交由宿主OS,经CPU处理最终交由
    宿主机的物理网卡,将包发出。

2. Para-Virtualization:半虚拟化(又称PV)
  让GuestOS内核明确知道自己是工作虚拟环境中,要使用真实设备,可调用宿主机上专用的系统调用
 来访问宿主主机的物理硬件,而非自己直接访问【所谓系统调用可简单理解为:驱动】;如:可将GuestOS
 访问物理网卡做成系统调用,当GuestOS需要访问物理网卡时,就可明确告诉它可直接通过系统调用来访问
 物理网卡,这样可绕过宿主OS的参与直接完成访问,其效率更高;由此来说CPU的指令集也是可以做出
   系统调用的,这样做不仅可让GuestOS执行效率更高,而且还可去掉监听,捕获,及模拟指令集等冗余模块。
   但这就必须涉及到系统内核的修改,因此对于开源的Linux是可行的但对于闭源的Windows则是不可以的。
 【注意:上面提到到虚拟机专用的System Call,实际是Hypervisor Call,它又叫:Hypercall】

   

3. PV on HVM(Para-Virtualization on Hardware Virtual Machine)
  PV和硬件虚拟化技术结合起来用,可让虚拟化不受OS的限制;用PV可解决开源OS中CPU的半虚拟化;
 而Intel的VT-X和AMD的AMD-V可实现对CPU的硬件虚拟化,由硬件来完成GuestOS发出的特权指令的转换,
 而无需将CPU的特权指令输出为Hypercall;而对于I/O(磁盘和网卡)和内存依然采用PV的方式实现。

 

虚拟机的三种通用模型:
  第一种模型:OS+VMM 实现了Hypervisor的功能。这种是工作站中常见的模型,典型的有VMware Workstations。
  第二种模型:VMM直接运行在硬件层之上,并提供硬件所需要的所有驱动,同时还提供了一个OS内核
    所必须的各种功能,但这些功能通常是专门为运行在其上的虚拟机而设计的,如:创建,删除虚拟机等。。
    典型的有:VMware ESX,和VMware ESXi
  第三种模型:Xen模型,Xen这种模型比较特殊,它虽然直接运行于硬件层之上,但它却并没有提供驱动所有硬件
    的驱动,它仅仅提供了主要设备CPU,Interrupt(中断),Memory的驱动,因此它采用了一种取巧的方式,
    要安装Xen就先安装一个主虚拟机,由它来驱动底层硬件;而所有虚拟机要访问CPU,Interrupt,内存时,
    Xen才自己来调度,为每个VM提供服务;在Xen中每台VM都被称为一个Domain,它们安照顺序排列
    Dom0是Xen中在主VM,它也是特权VM。

  

三种模型所演变的五种虚拟机模型如下:

1. Xen模型的基本工作原理:
  在Xen模型中Xen将管理GuestOS(GuestOS在Xen中被称为DomU)的功能给了Dom0,当DomU要创建一个网卡,
 在实现上是在Dom0上创建虚拟网卡软件,DomU仅显示已创建即可,当DomU要访问物理网卡时,DomU实际是先将包发给
 Xen的Hypercall,接着由Hypercall将请求转给Dom0的虚拟网卡(Vnet),最后Dom0对I/O硬件有直接操作的能力,因此
 它直接绕过Xen将请求交给物理网卡发出;仅当DomU和Dom0要访问CPU,内存,中断时,才直接有Xen来调度处理。

  

    Xen支持三种虚拟化类型:
  PV(纯半虚拟化): 
    Xen是原生支持虚拟化的“先锋人物”,若CPU,IO,Memory都不支持硬件虚拟化,Xen也可
  提供高性能的半虚拟化方案,因为Xen使用Dom0来直接管理硬件,DomU要访问硬件时,先将请求
  发给Xen的HyperCall并由Hypercall将请求转交给Dom0的虚拟硬件,最终由Dom0的虚拟硬件将请求
  直接发给物理设备。
  PV on HVM:
    若构建Xen的硬件环境中,CPU支持AMD-V 或 VT-X,Memory支持AMD的NPT 或 Intel的EPT,
  则Xen可以直接实现PV on HVM。这种性能最佳
  Full:
    Xen是可以直接实现完全虚拟化的,在完全虚拟化中,Dom0可通过软件模拟I/O , CPU指令集 和 其他硬件,
  做为DomU的OS也无需修改操作系统的内核就可以直接运行在这种模式下,但其最大的缺点也很明显,就是
  通过软件模拟的硬件性能会很差;但若CPU支持硬件虚拟化,也可在一定程度上提升性能。

   Xen的重要工具和组件:
  Qemu:Qemu是Dom0用来创建虚拟硬件的主要组件;Qemu最先是由法国的一位天才程序员开发的可跨
    平台的硬件模拟器,其大小1M左右,小巧精悍,如:底层物理处理器是X86平台,使用Qemu就可模拟
    一个苹果的ARM处理器,甚至是PowerPC处理器,若上层模拟的处理器与物理处理器一致,它还可以
    起到一定程度的硬件加速功能;通常Xen与Qemu共同使用,来为虚拟机建立模拟的网卡,硬盘(它
    甚至可以模拟VMware的虚拟硬盘)等。
  XM:它是Xen提供的VM管理工具,如创建,删除,暂停,关闭,快照虚拟机等,XM主要是借助与Xen
    输出的API接口实现这些功能的。XM还可借助Xen的API为虚拟机动态添加CPU,且可模拟多颗,
    不受物理CPU个数的限制。
  Openstand:它是XM的一种图形实现方式,它的功能也非常强大。

2. 第二种虚拟化模型---------KVM(Kernel-based Virtual Machine:基于内核的虚拟机)
  KVM最早是以色列的一家软件公司开发的,后被Redhat收购,Kernel2.6.20后KVM被整合到Kernel中,
 加上红帽对它的大力支持,现在KVM也是相对不错的。

 KVM的工作方式是:
  将虚拟OS运行于用户空间,它们就向进程一样,而这些虚拟的GuestOS的所有硬件都是由Qemu模拟出来的,
     如网卡,硬盘等,GuestOS要访问物理设备,必须先将请求发给Qemu模拟的硬件设备,该设备实际是一个
     用户进程,由模拟的硬件负责将请求发给当前系统的内核来处理,最终由当前OS操作物理网卡完成数据发送。

    

    注意:Qemu它自身完全可以做为一个虚拟服务器使用,但为何不直接使用Qemu,而使用KVM? 
    其主要原因在于Qemu可模拟所有硬件但它模拟的硬件是做为一个进程运行于用户空间中的,
    而KVM确是运行在内核空间中的模块,它访问的硬件的速度比用户空间的进程更高效。
    KVM+Qemu:这个组合仅限于64位平台,且CPU必须支持硬件虚拟化(VT-X或AMD-V)。

  KVM和Xen被加入内核的时间 
    内核版本2.6.20 以后KVM被整合到Kernel中。
    2.6.37后,可运行DomU的Xen被加入Kernel。
    3.0.0后 运行于Dom0中的Xen也被加入内核。

  Xen最早是由英国剑桥大学主导开发,现在以被Citrix(思杰)收购【思杰:全球第二大虚拟化解决方案提供商】
  KVM: virtio 是红帽提供的对KVM的I/O半虚拟化的增强技术,目前KVM已经支持透传I/O技术。


3. 第一种虚拟化模型----------Container(容器)
  这种虚拟化解决方案是每个用户空间就是一个GuestOS,他们都被模拟出了一个硬盘,网卡等设备,
 他们使用公共的OS,其性能比两个内核的虚拟化要高的多。但缺点也是很明显的,每个虚拟机之间的
 隔离性较差,若一个VM将OS搞崩溃了,则所有的VM全部都会崩溃;虽有这方面的隐患,但目前其稳定性
 也是比较可以的。 
  目前较流行的有:Docker,OpenVZ, Solaris Container, BSD Jails

  

4. 第一种虚拟化模型----------模拟器实现的虚拟化:
 模拟硬件层:使用类似于Qemu的工具,来模拟所有GuestOS需要的硬件(如:CPU,内存,硬盘等....)
  这种方式其迁移将变的非常方便,但其性能很差,这种完全虚拟化方案中Guestos的所有操作都由虚拟硬件翻译后,
  交由宿主OS执行。

    

5. 最后一种也是第一种模型,其实就类似于VMware Workstation,VirtualBox

 

附件1:
1974年Pepek 和 Goldberg在一篇论文中定义了“经典虚拟化(Classical virtualization)"的基本需求,
他们认为,一款真正意义上的VMM至少符合三个方面的标准:
 1》等价执行(Equivalient Execution):除了资源的可用性及时间上的不同之外,程序的在虚拟化环境中
   及真实环境中的执行是完全相同的。
    2》性能(Performance):指令集中的大部分指令要能够直接运行于CPU上;
    3》安全(Safety):VMM要能够完全控制系统资源; 

X86平台实现虚拟化技术的挑战:
  X86处理器有4个特权级别,Ring 0 ~ Ring 3,只有运行在Ring 0~2级时,处理器才可访问特权资源或执行
特权指令;运行在Ring 0级时,处理器可以允许所有的特权指令,x86平台上的操作系统一般只使用Ring 0 和
Ring 3两个级别,其中,操作系统运行在Ring 0级,用户进程在Ring 3级。

特权级压缩(Ring compression)
  为了满足上面所述的需求,VMM自身必须运行在Ring 0级,同时为了避免GuestOS控制系统资源,GuestOS
不得不降低自身的运行级别而运行于Ring 1 或 Ring 3(Ring 2不使用),此外,VMM使用分页或段限制的方式
保护物理内存的访问,但是64位模式下段限制不起作用,而分页又不区分Ring 0,1,2 为了统一和简化VMM的设计,
GuestOS只能和用户进程一样运行在Ring3。 VMM必须监视GuestOS对GDT, IDT(这些是CPU的敏感寄存器,
如:指令寄存器)等特权资源的设置,防止GuestOS运行在Ring 0级,同时又要保护降级后的GuestOS不受Guest
进程的主动或无意破坏。

特权级别名(Ring Alias)
  设计上的原因,操作系统假设自己运行于Ring 0,然而虚拟化环境中的GuestOS实际上运行于Ring1或 Ring 3,
由此,VMM必须保证各GuestOS不能得知其正运行于虚拟机中这一事实,以免其打破前面的“等价执行”标准,
例如:x86处理器的特权级别存放在CS代码段寄存器内,GuestOS却可以使用非特权PUSH指令将CS寄存器压栈,
然后,POP出来检查该值;又如:GuestOS在低特权级别时读取特权寄存器GDT,LDT,IDT和TR(这些是CPU内部
的敏感寄存器,如:指令寄存器...)时并不发生异常,这些行为都不同于GuestOS的正常期望。

地址空间压缩(Address Space Compression)
  地址空间压缩是指VMM必须在GuestOS的地址空间中保留一段供自己使用,这是x86虚拟化技术面临的另一个挑战。
VMM可完全运行于自有地址空间,也可部分运行于GuestOS的地址空间,前一种方式,需在VMM模式与GuestOS模式
之间切换,这会带来较大的开销此外,尽管运行于自己的地址空间,VMM依然需要在GuestOS的地址空间保留出一部分
来保存控制结构,如IDT和GDT。无论是哪一种方式,VMM必须保证自己用到的地址空间不会受到GuestOS的访问后修改。

非特权敏感指令
  x86使用的敏感指令并不完全隶属于特权指令集,VMM将无法正确捕获此类指令并作出处理。例如,非特权指令SMSW在寄存器
中存储的机器状态就能够被GuestOS所读取,这违反了经典虚拟化理论的要求。

静默特权失败(Silent privilege Failures)
  x86在某些特权指令在失败时并不返回错误,因此,其错误将无法被VMM捕获,这将导致其违反经典虚拟化信条中的“等价执行”法则。

中断虚拟化(Interrupt Virtualization)
  虚拟化环境中,屏蔽中断及非屏蔽中断的管理都应该有VMM进行,然而,GuestOS对特权资源的每次访问都会触发处理器异常,
这必然会频繁屏蔽或启用中断,若这些请求均由VMM处理,势必会极大影响整体系统性能。

X86平台虚拟化
  完整意义上的计算机由硬件平台和软件平台共同组成,根据计算机体系结构理论,其硬件平台包括CPU,内存和各种I/O设备;
而软件平台则包括BIOS,操作系统,运行时库及各种应用程序,对于主机虚拟化技术来讲,其主要负责虚拟硬件平台及BIOS,而
操作系统,运行时库及各种应用程序可使用以往在物理平台上各种现在技术及产品。

posted @ 2020-01-05 17:44  星火撩原  阅读(555)  评论(0编辑  收藏  举报