8.3.4 准虚拟化

运行在I型和II型管理程序之上的都是没有修改过的客户操作系统,但是这两类管理程序为了获得合理的性能都备受煎熬。另一个逐渐开始流行起来的处理方法是更改客户操作系统的源代码,从而略过敏感指令的执行,转而调用管理程序调用。事实上,对客户操作系统来说就像是用户程序调用操作系统(管理程序)系统调用一样。当采用这种方法时,管理程序必须定义由过程调用集合组成的接口以供客户操作系统使用。这个过程调用集合实际上形成了API(应用程序编程接口),尽管这个接口是供客户操作系统使用,而不是应用程序。

再进一步,从操作系统中移除所有的敏感指令,只让操作系统调用管理程序调用(hypervisor call)来获得诸如I/O操作等系统服务,通过这种方式我们就已经把管理程序变成了一个微内核,如图1-26所示。一些或全部敏感指令有意移除的客户操作系统称为准虚拟化的(paravirtualized)(Barham等人,2003;Whitaker等人,2002)。仿真特殊的机器指令是一件让人厌倦的、耗时的工作。它需要调用管理程序,然后仿真复杂指令的精确语义。让客户操作系统直接调用管理程序(或者微内核)完成I/O操作等任务会更好。之前的管理程序都选择模拟完整的计算机,其主要原因在于客户操作系统的源代码不可获得(如Windows)、或源代码种类太多样(如Linux)。也许在将来,管理程序/微内核的API接口可以标准化,然后后续的操作系统都会调用该API接口而不是执行敏感指令。这样的做法将使得虚拟机技术更容易被支持和使用。

全虚拟化和准虚拟化之间的区别如图8-27所示。在这里,我们有两台虚拟机运行在支持VT技术的硬件上。左边,客户操作系统是一个没有经过修改的Windows版本。当执行敏感指令的时候,硬件陷入到管理程序,由管理程序仿真执行它随后返回。右边,客户操作系统是一个经过修改的Linux版本,其中不含敏感指令。当它需要进行I/O操作或修改重要内部寄存器(如指向页表的寄存器)时,它调用管理程序例程来完成这些工作,就像在标准Linux系统中应用程序调用操作系统系统调用一样。

广告:个人专属 VPN,独立 IP,无限流量,多机房切换,还可以屏蔽广告和恶意软件,每月最低仅 5 美元

如图8-27所示,管理程序被一条虚线分成两个部分。而在现实中,只有一个程序在硬件上运行。它的一部分用来解释陷入的敏感指令,这种情况下,请参照Windows一边。另一部分用来执行管理程序例程。在图8-27中,后一部分被标记为“微内核”。如果管理程序只是用来运行准虚拟化的客户操作系统,就不需要对敏感指令进行仿真,这样,我们就获得了一个真正的微内核,这个微内核只提供最基本的服务,诸如进程分派、管理MMU等。I型管理程序和微内核之间的界限越来越模糊,当管理程序获得越来越多的功能和例程时,这个界限变得更加不清晰。这个主题是有争议的,但是这一点越来越明确:以内核态运行在硬件上的程序应当短小、可靠,由数千行代码而不是数百万行代码组成。这个话题已经经过很多学者的讨论(Hand等人,2005;Heiser等人,2006;Hohmuth等人,2004;Roscoe等人,2007)。

阅读 ‧ 电子书库
图 8-27 支持全虚拟化和准虚拟化的管理程序

对客户操作系统进行准虚拟化引起了很多问题。第一,如果所有的敏感指令都被管理程序例程所代替,操作系统如何在物理机器上运行呢?毕竟,硬件不可能理解管理程序例程。第二,如果市场上有很多种管理程序,例如Vmware、剑桥大学开发的开源项目Xen、微软的Viridian,这些管理程序的API接口不同,应该怎么办呢?怎样修改内核使它能够在所有的管理程序上运行?

Amsden等人(2006)提出了一个解决方案。在他们的模型当中,当内核需要执行一些敏感操作时会转而调用特殊的例程。这些特殊的例程,称作VMI(虚拟机接口),形成的低层与硬件或管理程序进行交互。这些例程被设计得通用化,不依赖于硬件或特定的管理程序。

这种技术的一个示例如图8-28所示,这是一个准虚拟化的Linux版本,称为VMI Linux(VMIL)。当VMI Linux运行在硬件上的时候,它链接到一个发射敏感指令来完成工作的函数库,如图8-28a所示。当它运行在管理程序上,如VMware或Xen,客户操作系统链接到另一个函数库,该函数库提供对下层管理程序的适当(或不同)例程调用。通过这种方式,操作系统的内核保持了可移植性和高效性,可以适应不同的管理程序。

阅读 ‧ 电子书库
图 8-28 VMI Linux运行在:a)硬件裸机;b)VMware;c)Xen上

关于虚拟机接口还有很多其他的建议。其中比较流行的一个是paravirt ops。它的主要思想与我们上面所介绍的相似,但是在细节上有所不同。