为了正常的体验网站,请在浏览器设置里面开启Javascript功能!

计算系统虚拟化

2017-11-29 50页 doc 2MB 8阅读

用户头像

is_830073

暂无简介

举报
计算系统虚拟化计算系统虚拟化 前 言 ........................................................................................................... 错误~未定义书签。I 目 录 .......................................................................................................... 错误~未定义书签。1 第一章 概 述 .......
计算系统虚拟化
计算系统虚拟化 前 言 ........................................................................................................... 错误~未定义书签。I 目 录 .......................................................................................................... 错误~未定义书签。1 第一章 概 述 .......................................................................................................................... 6 1.1 虚拟化简介 ........................................................................................................................................... 6 1.2 虚拟化技术的发展与分类 .................................................................................................................... 7 1.2.1 发展历程 .............................................................................................................................................. 8 1.2.2 虚拟化技术的分类 ............................................................................................................................. 10 1.3 虚拟化的相关研究内容 ...................................................................................................................... 24 1.3.1 多计算系统的虚拟化 .......................................................................................................................... 25 1.3.2 虚拟用户使用环境 ............................................................................................................................. 26 1.3.3 虚拟计算系统的安全可信机制 ........................................................................................................... 28 1.3.4 虚拟计算系统的性能评测 .................................................................................................................. 29 1.4 虚拟化的应用 ..................................................................................................................................... 30 1.4.1 虚拟化在高效能计算机中的应用 ....................................................................................................... 30 1.4.2 虚拟化仿真技术的应用 ...................................................................................................................... 32 1.5 各章内容简介 ..................................................................................................................................... 34 第二章 指令级虚拟化 ............................................................................................................ 36 2.1 二进制翻译技术概览 .......................................................................................................................... 36 2.1.1 解释执行 ............................................................................................................................................ 36 2.1.2 静态二进制翻译 ................................................................................................................................. 36 2.1.3 动态二进制翻译 ................................................................................................................................. 38 2.1.4 二进制翻译系统框架 .......................................................................................................................... 39 2.1.5 动态优化 ............................................................................................................................................ 40 第三章 计算系统虚拟化方法 ................................................................................................ 42 3.1 系统级虚拟化概述 ............................................................................................................................. 42 3.2 CPU虚拟化 ........................................................................................................................................ 43 3.2.1 经典虚拟化的逻辑模型 ...................................................................................................................... 43 3.2.2 x86的CPU虚拟化方法 ..................................................................................................................... 44 3.2.3 虚拟CPU的调度................................................................................................................................ 46 3.2.4 小结 .................................................................................................................................................... 47 3.3 内存虚拟化 ......................................................................................................................................... 47 3.3.1 内存虚拟化的基本原理 ...................................................................................................................... 47 3.3.2 内存虚拟化的优化机制 ...................................................................................................................... 51 3.3.3 小结 .................................................................................................................................................... 52 3.4 I/O虚拟化 .......................................................................................................................................... 53 3.4.1 当前I/O设备虚拟化的几种方法........................................................................................................ 53 3.4.2 虚拟机的直接I/O访问....................................................................................................................... 55 3.4.3 小结 .................................................................................................................................................... 56 3.5操作系统适配 ............................................................................................................................................ 56 3.5.1 迁入虚拟化环境 ................................................................................................................................. 56 3.5.2 支持虚拟机管理 ................................................................................................................................. 59 3.5.3 为特殊项目定制 ................................................................................................................................. 60 3.5.4 虚拟装置(Virtual Appliance) .......................................................................................................... 61 3.5.5 小结 .................................................................................................................................................... 63 第一章 概 述 1.1 虚拟化简介 虚拟化是继互联网之后,又一个对整个信息产业有突破性的信息技术。从历史上看,虚拟化并不是一项全新的技术。早在上个世纪60年代,美国计算机学术界就开始了虚拟技术的萌芽,首次提出了虚拟化的概念,但那时的虚拟技术只是应用在大型主机上。时至今日,伴随着IT硬件的丰富化、多样化以及一些软件公司如VMware、Xen、微软等推出不同的虚拟化软件之后,虚拟化进驻的应用领域已经逐渐拓展,虚拟化技术已经得到了大幅度提升。目前出现的许多不同种类的虚拟化解决,致力于从不同的角度解决不同的系统性能问,使得虚拟化技术的内容越来越丰富。虚拟化生态链系统趋于标准化也体现了虚拟化技术的良好前景。 正如“虚拟”是“真实”的反义词一样,在计算机领域,“虚拟计算”也是“真实计算”的反面。在解释“虚拟计算”的含义前,我们先来回顾一下传统的真实计算。举个例子,我们希望用计算机运行某个程序或软件,需要先购置一台满足该程序或软件运行需求的计算机硬件(这时需要慎重选择CPU主频、内存容量、硬盘容量等技术参数),然后在该硬件上安装操作系统,配置运行环境,最后才能够运行我们希望的程序或软件。而程序或软件的运行,几乎是独占购置的全部计算资源。在这种情形下,我们的计算建立在真实计算机硬件基础之上。 虚拟计算技术则强调为需要运行的程序或软件营造它所需要的执行环境。在采用了虚拟计算技术后,程序或软件的运行不一定独享底层的物理计算资源,对它来说,它只是运行在一个与上面论述的“真实计算”完全相同的执行环境(具有相同的CPU主频、内存和硬盘容量)中,而其底层的硬件可能与之前所购置的计算机完全不同。 虚拟化的概念在现代操作系统的设计与实现中已有所体现。例如,32位操作系统的虚拟内存技术,采用内存页面与外存(主要是 硬盘)间换入换出的办法,为系统的每个执行实体(进程)虚拟出4GB内存空间(尽管计算机实际物理内存远远小于4GB)。同时,在现代多任务操作系统中,每个执行实体在运行过程中都会感觉自己独占处理器资源,而实际上,它们采用分时复用的思想,由操作系统调度,多个进程轮转执行,这也是虚拟化思想体现在现代操作系统中的一个例子。 虚拟计算技术的引入,打破了真实计算中软件与硬件之间的紧密耦合关系,为计算带来新的活力,解决了真实计算的很多问题。例如,在上例中,当程序或软件本身发生变化(这种变化往往是经常性的)后,以前购置的计算机硬件要么因为计算能力太强而变得浪费,要么因为计算能力不够而需要重新购买新硬件。 关于虚拟计算(Virtualization)的定义,人们提出了多种不同的看法。G. Popek和R. Goldberg在他们的[G. Popek et al.,1974]中提到,虚拟计算具有以下三个特点: (1) Fidelity(保真性):这一特点强调应用程序在虚拟机上执行,除了时间因素外(会比在物理硬件上执行慢一些),将表现为与在物理硬件上相同的执行行为; (2) Performance(高性能):这一特点强调在虚拟执行环境中应用程序的绝大多数指令能够在虚拟机管理器不干预的情况下,直接在物理硬件上执行; (3) Safety(安全性):物理硬件应该由虚拟机管理器全权管理,被虚拟出来的执行环境中的程序(包括操作系统)不得直接访问硬件。 由于希望尽量减少性能上的损失,这一定义强调在虚拟执行环境中应用程序的绝大多数指令能够直接在物理硬件上执行,从而排除了很多的虚拟机系统,显得比较狭义。 在本书中,我们将采用广义的虚拟计算定义:虚拟计算是一种采用软硬件分区、聚合、部分或完全模拟、分时复用等方法来管理计算资源、构造一个或多个计算环境的技术。 1.2 虚拟化技术的发展与分类 虚拟化技术的起源可以追溯到上世纪五十年代末,至今已有几十年时间。1959年,计算机科学家Christopher Strachey发表了一篇 名为《大型高速计算机中的时间共享》(Time Sharing in Large Fast Computers)的学术报告[C. Strachey, 1959],他在文中首次提出了虚拟化的基本概念,被认为是虚拟化技术的最早论述。 1.2.1 发展历程 虚拟化技术真正的开发从上世纪六十年代才开始。IBM公司最早发明了一种操作系统虚拟机技术,允许用户在一台主机上运行多个操作系统,让用户尽可能地充分利用昂贵的大型机资源。最早使用这项技术的是IBM 7044 计算机,它基于麻省理工学院(MIT)开发的分时系统CTSS(Compatible Time Sharing System) [Fernando J. Corbato, 1963] 和曼彻斯特大学的Atlas项目(世界最早的超级计算机之一)而开发,首次使用了请求调页和系统管理程序调用。1960年到1979年之间,IBM以及其他几家公司陆续开发了一批具有虚拟机功能的产品,比如型号为Model 67的System/360主机,可以虚拟所有硬件接口。“M44/44X”计算机项目定义了虚拟内存管理机制,可以为多个用户的程序提供独立的计算环境。之后,IBM更是认识到虚拟化技术的重要性,IBM360/40,IBM360/67,以及VM/370虚拟计算系统的相继问世,在当时都具有虚拟机功能。在任何一个配置这些虚拟系统的环境中,用户能够运行当时流行的任何一种操作系统。 另一个早期使用的虚拟化技术是仿真处理器,也叫做P-code(or pseudo-code)机。P-code是一种机器语言,运行在虚拟机上而不是实际硬件。P-code语言在1970年由加州大学圣地亚哥分校的Pascal系统项目组开发,可以把Pascal程序编译成P-code代码,然后在具有P-code功能的虚拟机上运行。P-code程序具有高度可移植性,能够运行在任何具有P-code功能的虚拟机上。后来的Java虚拟机采用P-code模型,从而可以通过简单移植JVM程序到新架构的机器上来广泛发布Java程序[M. Tim Jones, 2006]。 可以看到,在虚拟化技术萌芽的上世纪六、七十年代,人们研究虚拟计算的目标是对相对昂贵的硬件资源进行充分利用,通过虚拟机手段让更多的人能够通过终端设备接触和使用计算机系统。从这一点来说,虚拟机技术的发明是一项了不起的成就,它能够让更多的用户更好地共享当时非常昂贵的计算机资源。但是,到上个世纪七、八十年代,随着大规模集成电路的出现和个人电脑的普及,计算机硬件变得越来越便宜。当初为共享昂贵硬件而设计的虚拟化技术慢慢无人问津,而只是在高档服务器(如IBM小型机)中继续存在。 近年来,虚拟机以及计算虚拟化技术重新成为计算机体系结构领域的研究热点,其原因主要有以下两个方面:其一,计算机系统经过多年发展,在变得越来越强大的同时,也在变得越来越难以管理(例如今天的网络系统、分布式计算系统),软硬件(TCO)管理开销(特别是电费开销)也逐年增加。特别是随着处理器多核化时代的到来、冗余计算资源的引入,这一矛盾势必越来越尖锐。其二,今天的计算,已经从以前以计算机为中心向以用户为中心的服务计算过渡,人们更关心的是计算系统能够为用户提供怎样的接口和提供怎样的服务,以适应用户复杂和多样化的需求。在这一背景下,由于计算系统虚拟化技术既能够屏蔽底层复杂的物理环境,又能够为用户提供可配置的使用环境,就自然重新成为工业界和学术界的研究热点。 在以前的虚拟化历程中,x86架构并没有成为虚拟化技术发展的受益者,主要原因是x86架构在设计之初并没有考虑支持虚拟化技术,它本身的结构和复杂性使得在其之上进行虚拟化非常困难。然而,上个世纪九十年代末期,VMware和其他虚拟化软件厂商率先为虚拟化技术在x86服务器环境下开辟了道路,使得虚拟化应用的前景更加广阔。他们实施的是一种软件解决方案,以虚拟机监视器(VMM)为中心使PC服务器平台实现虚拟化。然而,在这种纯软件的“完全虚拟化”模式中,每个客户机操作系统获得的关键平台资源都需要VMM控制,并由它来分配,以避免发生冲突。为了处理这些相关的控制,需要利用二进制转换来进行操作,而二进制转换的开销使得“完全虚拟化”的性能大打折扣。为解决这个问题,引出了另一种新的虚拟化模式,即在Denali项目和Xen项目中出现了“半虚拟化”技术。半虚拟化的实施不需要二进制转换,而是通过对客户机操作系统进行代码级修改,从而为操作系统提供新的接口,以使新的、定制的客户操作系统获得额外的性能和高扩展性。但是,修改客户机操作系统非常繁琐,带来了一些系统指令级别冲突以及运行效率的问题,需要软件开发商、集成商等投入大量的时间和人力对系统进行优化。此时,虚拟化技术的发展走到了硬件支持阶段,使半虚拟化的障碍得到了解决。硬件虚拟化技术就是把纯软件虚拟化技术的各项功能用硬件电路来逐一实现。作为发挥多核处理器性能的一个有效手段,Intel和AMD都在硬件级提供了对虚拟化的支持,比如Intel的VT技术和AMD的SVM技术。Intel的VT技术提供了一个名为VMX Root的新特层阶级,该级别专门用于运行VMM,它对标准x86架构进行了优化。在消除了对CPU半虚拟化和二进制转换技术的需求后,硬件已经能支持多种未经修改的客户机操作系统直接运行,VMM的设计得到极大简化,进而使 VMM能够按通用标准进行编写,减少了相关的性能开销,性能更加强大。 回顾自上世纪九十年代起这一阶段的虚拟化技术发展历程,从纯软件的虚拟化(完全虚拟化、半虚拟化),再到硬件支持的虚拟化,突破了在x86平台上进行虚拟化的瓶颈,进驻的应用领域飞速增加。逐步扩展的技术路线证实了虚拟化技术在不断的挑战和创新中逐 渐完善与成熟。多核平台出现后,计算机系统性能需要均衡发展,存储虚拟化技术、I/O虚拟化技术等也都得到了成比例的提升,使得多核处理能力被最大限度地发挥。然而毋庸置疑,目前业界的虚拟化技术仍然还很不完善。比如多机虚拟化技术的研究仍处在初级阶段,已有的虚拟化方法并不能完全满足高效能计算机的需求。由于不同虚拟化方法引入的性能开销等问题,使其无法良好地适应一部分较敏感的高性能计算系统。而目前异构成为高效能计算机系统的重要发展趋势,恰恰又需要虚拟化技术作为结合手段来调整异构带来的复杂性。此外,虚拟计算系统使用环境、虚拟化安全可信机制、虚拟计算系统性能评测手段等都在进一步地研究和发展之中。关于这些相关技术的研究,本书将在以后的章节中陆续讨论。接下来,我们继续从虚拟化发展的历程中抽取不同阶段所使用的技术特征,对其进行分类介绍。 1.2.2 虚拟化技术的分类 为了满足不同的功能需求,目前已出现了许多不同种类的虚拟化解决方案,由于其采用不同的实现方式和抽象层次,使得这些虚拟化系统呈现出不同的特性。计算机系统的设计本身采用分层结构(如图1.1所示)。首先,计算机硬件为直接运行在其上的软件(操作系统)提供的接口是一组指令集合(Instruction Set Architecture,简称ISA),不同处理器硬件提供的接口不尽相同,例如Intel奔腾系列提供的接口是著名的x86指令集,它基于复杂指令系统(Complex Instruction Set Computer,简称CISC);而IBM公司生产的Power系列处理器则提供基于精简体系(Reduced Instruction Set Computer,简称RISC)的指令集合。理论上,如果操作系统希望在一个特定的硬件上运行,就必须遵守和使用该硬件提供的指令集。 为方便上层应用程序的开发,一个完善的操作系统往往会提供一组程序开发库(Libraries),这些库为应用程序的编写提供了大量的接口(称为应用程序编程接口,API),使得应用程序在编写时不用直接调用操作系统提供的更底层的功能,从而减轻了程序员的工作负担。 理论上,虚拟化技术采用的抽象层次可以在这几层中自由选取。由于选择的多样性,也就决定了虚拟化技术的多样性。然而,我们看到,在这种多样性背后,虚拟化技术的实质是一样的:它将底层资源进行分区,并向上层提供特定的和多样化的执行环境。 应用程序 应用编程接口(API) 程序库 系统调用(SysCall) 操作系统 指令集合(ISA) 硬件 图1-1 计算机系统结构的层次关系 结合当前主流的虚拟化解决方案和计算机系统结构,我们站在虚拟机实现所采用的抽象层次的角度对虚拟化系统进行分类。 1.2.2.1 指令级虚拟化 指令集架构级虚拟化通过纯软件方法,模拟出与实际运行的应用程序(或操作系统)所不同的指令集去执行,采用这种方法构造的虚拟机一般称为模拟器(Emulator)。一个典型的计算机系统由处理器、内存、BUS、硬盘驱动器、磁盘控制器、定时器、多种I/O设备等等部件组成。模拟器通过将客户虚拟机发出的所有指令翻译成本地指令集,然后在真实的硬件上执行。这些指令包括典型的处理器指令(例如x86中的add,sub,jmp等等)和特殊的I/O指令(例如in/out指令)。当然,一个模拟器要成功的模拟一个真实的机器,它必须能够模拟真实机器所能做的一切事情,包括读ROM芯片、重启、系统开关等等。 这种类型的虚拟机结构,就其简单性和健壮性而言非常好,但同时,它还具有其它一些优点和缺点。就优点而言,这种类型的虚拟机能够实现应用以及操作系统的跨平台执行。由于模拟器的工作原理是将虚拟执行环境中的指令翻译成主机平台上的指令来执行,因此只要能够通过主机平台上的指令来完成虚拟执行环境中与指令相同的任务,当客户平台的架构改变时,它也可以很容易的适应平台的变化。这样,它在客户平台和主机平台之间就没有执行严格的绑定。例如,模拟器能够让原来运行在x86结构上的操作系统和应 用程序在PowerPC系列处理器、甚至是为嵌入式系统而设计的Arm系列处理器上运行。然而,架构的便携性也带来一些性能上的开销。因为由仿真计算机发出的每一条指令都需要用软件方法来解释,这就导致较大的性能损失。以下简要介绍几个较典型的模拟器系统。 (1)Bochs Bochs[Kevin Lawton et al., 2003]是由Kevil Lawon领导的一群爱好者用C++编写的开放源代码的x86 PC模拟器。它可以运行在最流行的平台上,包括x86、PowerPC、Alpha、Sun和MIPS,并可编译模仿大多数版本的x86机器。Bochs翻译每一条指令,从加电到重新启动模拟Intel x86 CPU,定制BIOS并为所有标准PC外围设备装配设备模型,以这种方式,Bochs可以支持无修改的软件执行(包括操作系统)。但由于Bochs模拟x86软件,导致指令翻译的额外开销。 (2)Crusoe Transmeta的VLIW是一个基于Crusoe[Transmeta, 2000]、带有动态x86模拟器的处理器,也叫做“代码变形引擎”。它能执行任何基于x86的应用程序。虽然最初的意图是创建一个更简单、更小、耗电更少的芯片,其中Crusoe就是一种,但只有少数编译的研究人员以这种新处理器为目标。因此,随着一些额外硬件支持、扩展缓存和其它优化,带有x86模拟器的Crusoe发布了。它利用16MB系统内存作为“翻译缓存”,即存储最近x86到VLIW指令翻译的结果以备将来使用。并且,它被设计成用于处理x86指令集精确的异常语义,并且不用限制预测调度。Alias硬件也帮助Crusoe重新整理代码以使代码被优化装载。所有这些技术都极大地提高了Crusoe处理器的性能,使其在保持小巧而节能优点的同时,能够支持所有现有的x86操作系统和应用程序。 (3)QEMU QEMU[F. Bellard, 2005]是一个使用便携式动态翻译器的快速处理器模拟器。它支持两种操作模式:单纯用户空间和完整系统仿真。在前一个模式中,QEMU可以将在CPU上编译的Linux进程装载到另一个CPU中,或者跨编译和交叉调试。在后一个模式中,它可以模拟完整系统,包括处理器和外围设备。QEMU采用基本块作为独立的翻译单元。在动态翻译过程中,它将遇到的每一块代码都转换成主机指令集。与Bochs不同的是,它支持许多处理器架构的模拟,包括x86、ARM、PowerPC和Sparc,而Bochs只支持x86的客 户执行环境。另一方面,它像Crusoe一样,使用动态翻译以达到比较高的代码运行速度。 (4)BIRD BIRD[Susanta Nanda et al., 2005]是一个x86二进制的解释引擎,目前作为主机ISA只支持x86,同时也对其他平台进行扩展。它利用体系结构之间的相似性,尽可能执行本机指令,其他指令都通过软件仿真。除了解释,它为二进制分析提供了各种工具,包括二进制重写,这在消除安全漏洞和代码的优化方面非常有用。它结合了静态以及动态的分析和翻译技巧来提高基于x86程序的仿真效率。 1.2.2.2 硬件级虚拟化 硬件抽象层面(Hardware Abstraction Layer,即HAL)虚拟化实际上与指令集架构级虚拟化非常相似,其不同之处在于,这种类型的虚拟化所考虑的是一种特殊情况:客户执行环境和主机具有相同指令集合的情况,并充分利用这一特点,让绝大多数客户指令在主机上直接执行,从而大大地提高了执行的速度。今天,大部分商业虚拟化软件在流行的x86平台使用此虚拟化技术来提高效率,说明了这类虚拟化技术的可行性与实用性。该虚拟化技术可以将虚拟资源映射到物理资源并在虚拟机计算中使用本地硬件。当模拟机需要访问关键物理资源时,模拟器接管其物理资源并妥善地多路复用。 这种虚拟化技术要能够正确工作,所构造的虚拟机(VM)必须对其中的一些特权指令(例如修改页表等操作)进行处理,执行时产生陷入并将它传递给下层虚拟机管理器(VMM)执行。这是因为在VM中运行的未加修改的操作系统会利用特权指令得到CPU和内存资源。当某特权指令执行时产生一个陷入,便马上将指令发送给VMM,这使得VMM可以完全控制虚拟机并保持每个VM隔离。然后,该VMM在处理器中执行该指令,并将模拟结果及特权指令返回给VM。大多数商业虚拟机软件,都使用像代码扫描和动态指令重写这样的技术来解决这些问题。 本小节我们将探讨一些由商用虚拟机系统使用的技术。其中,VMware是一个业界实力很强的做虚拟机的公司,在本书的后续各章节中将根据需要从不同的技术细节展开讨论。这里,我们也尽可能地对VMware使用的虚拟技术做较全面的介绍。 (1)VMware VMware[Vmware.com]公司有三种不同层次的虚拟机产品: 用于桌面的VMware Workstation,用于企业服务器的VMware GSX Server和VMware ESX Server。 VMware公司虚拟机产品的部署可以分为两类:独立虚拟化(Standalone Virtualization)和基于主机操作系统的虚拟化(Hosted Virtualization)。其中独立虚拟化方法如图1-2所示。该虚拟化技术的特点是虚拟机管理器直接运行在物理硬件之上(这种模式又被称为Hypervisor模式),并在其上构造多个虚拟执行环境。在这种情况下,虚拟机管理器实质上既充当了主机操作系统又充当了虚拟机管理器。 应用程序应用程序 客户操作系统客户操作系统 客户虚拟机客户虚拟机 虚拟机管理器VMM 物理硬件 图1-2 独立虚拟化 基于主机操作系统的虚拟化方法如图1-3所示。这种虚拟化技术的特点是虚拟机管理器运行在主机操作系统之上,并借助主机操作系统去管理内存,完成处理器的调度、硬件驱动和资源管理[Jay Munro, 2001]。 应用程序应用程序 客户操作系统客户操作系统 客户虚拟机客户虚拟机 主机操作系统虚拟机管理器(VMM) 物理硬件 图1-3 基于主机操作系统的虚拟化 独立虚拟化技术的优点在于能够直接操纵硬件,实现对底层硬件的完全控制,避免了调用主机操作系统的额外开销。然而,由于底层的每一个硬件都需要设备驱动的支持,独立虚拟化就需要重新为这些底层硬件去开发驱动程序(这就需要几乎所有设备生产厂商的支持),所以独立虚拟化的缺点在于它通常在硬件支持方面非常有限。采用独立虚拟化技术的虚拟化软件主要应用在服务器领域,VMware ESX Server就是采用独立虚拟化技术构造服务器虚拟化软件的一个主要例子。 基于主机操作系统虚拟化技术的优缺点则正好与独立虚拟化技术相反,虽然通过主机操作系统间接地访问硬件导致了额外的开销,然而却不存在对底层硬件设备的支持问题。理论上,只要主机物理设备能够支持的硬件,虚拟机管理器软件都能支持,并能够将这些设备映射到它所构造的客户虚拟机中。这类虚拟化技术通常应用在对性能要求不是很高的场合(如桌面PC),VMware Workstation就是这类虚拟化软件的一个典型例子。 VMware产品针对基于x86的工作站和服务器,它必须考虑和解决多个基于x86的操作系统(客户虚拟机)并发执行的问题。然而,具有漫长历史的x86结构,在设计之初并没有考虑到虚拟化应用的需要。一些特权指令(如对全局描述符表GDT、全局中断描述符表IDT以及页表的修改、以及I/O指令)的存在,将可能导致一个(客户)操作系统的执行对主机状态的修改,而破坏其他操作系统的执行环境。VMware虚拟化软件通过patent-pending技术来解决这个问题,动态改写主机的部分代码,只要涉及到对硬件状态的修改就 插入陷阱,让虚拟机管理器来处理。虽然它解决了问题,但增加了翻译和执行开销。VMware通过缓存翻译指令,并尽可能地重用这些指令块来减小开销。然而,这又增加了一些难以避免的缓存代价。 IA32平台的工作方式可以帮助理解VMware Workstation软件是如何安装和运行的。在英特尔架构上,其保护机制提供了四个特权级别:从0到3。这些级别也称为环(ring)。这些保护环仅存在于i386以后的保护模式(Protected Mode)中,而目前流行的多任务操作系统(如Windows和Linux),都运行在该模式下。据英特尔公司称,环0指操作系统内核服务,环1和2为设备驱动,环3属于应用程序级。然而,在实际中,大多数操作系统和设备驱动在环0运行,在环3应用。特权指令只允许在环0执行,如果在其他以外的地方执行会造成保护冲突。 VMware Workstation软件由三个部分组成:VMX驱动、安装在环0的VMM以及在环3的VMware应用程序(VMApp)。VMX驱动器安装在操作系统内部,获得VMM所需要的特权级别。当执行时,VMApp将VMM装载入带有VMX驱动的内核内存,并授予其最高级别(环0)。在这一点上,主机操作系统也知道VMX驱动及VMApp,但却不知道VMM。现在该机器有两个世界:主操作系统和VMM。VMM可以直接访问处理器硬件或通过VMX驱动访问主操作系统。该系统的体系结构如图1-4所示。 (客户)应用程序 客户操作系统 VMware应用程序(主机)应用程序客户虚拟机(VMApp) 主机操作系统VMX驱动虚拟机管理器 磁盘PC 硬件 内存 CPU 图1-4 WMware Workstation软件的系统结构 当客户操作系统或运行在其上的应用程序只是进行纯粹的计算时,这些计算指令都通过虚拟机管理器(VMM)直接在物理CPU上执行(因为这些指令不会修改物理或虚拟硬件状态)。对于属于特权指令的I/O指令,它们的执行将陷入到虚拟机管理器中,并通过一个转换在主操作系统中执行。在客户虚拟机中要求的I/O操作被翻译成更高级别的I/O调用,并通过VMApp被主机操作系统调用, 结果通过交互返回给VMM。 新一代的VMware Workstation软件有一些突出特点。主机桌面的指针一体化(Pointer integration)允许将鼠标从VMWare应用程序的展示窗口中换进换出,就像其他任何基于窗口的应用程序一样。文件访问共享(File sharing)允许在主机和客户机之间共享文件,以使数据在虚拟机和主机之间的传输更加容易,其中数据可以用作备份或其他用途。动态调整屏幕大小(Dynamic display resizing)让用户可以动态的调整VMware应用程序的展示大小,就像其他任何窗口一样。事实上实现这些并非如此容易,每一次大小调整的操作都会改变虚拟机的屏幕。 VMware Workstation支持多种网络安装,使用户可以方便的连接到网络。它提供一个可以连接到虚拟机内所有以太网适配器的虚拟以太网集线器以使主机连接成一个局域网。同时它通过虚拟机外部与真实网络连接的以太网卡,支持桥接(Bridge)网络。它也支持网络地址转换(NAT)。在其它特性中,它将主机的USB设备传送给虚拟机,让用户在虚拟机内部实现对任何一个USB设备的连接和使用。 (2)Virtual PC 微软的Virtual PC[Microsoft, 2004]基于虚拟机管理器(VMM)架构,可以让用户创建和配置一个或多个虚拟机。它有一个undo disk,让用户可以轻易撤消虚拟机硬盘中的一些操作,使得数据在几种情况下易于恢复。并且,采用Virtual PC能够将Macintosh的机器虚拟成x86机器。但Virtual PC和VMware比起来还有一些缺点。Virtual PC不支持Linux、FreeBSD、OpenBSD以及Solaris等操作系统,同时也不支持SCSI设备。一旦配置完毕,它将无法改变虚拟机所拥有的硬件设备。 (3)Denali VMware Workstation和微软的Virtual PC所提供的虚拟机由于设计的局限性,很难完成大规模虚拟化。华盛顿大学的Denali项目[A. Whitaker et al., 2002]试图解决这个问题,提出了一个新的虚拟化架构来支持数以千计的虚拟机,称之为轻量级虚拟机。使用一种所谓的半虚拟化(Para-virtualization)技术,来增加虚拟机的扩展性。 这个半虚拟化技术改变了传统虚拟化架构,同时,这种新的体系结构为定制的操作系统提供了新的接口,以使新的、定制的客户 操作系统(不像VMware Workstation支持未修改的操作系统)获得额外的性能和高扩展性。 (4)Xen Xen[P. Barham et al, 2003]是剑桥大学的研究人员开发的一个开源项目,它提出了一个需要修改客户操作系统的虚拟化体系结构。虽然Xen与Denali[A. Whitaker et al., 2002]一样同是采用半虚拟化架构,但它们有着不同的目标。Denali的半虚拟化架构不用保证应用程序二进制接口(ABI)的兼容性,因为它用来支持数以千计运行网络服务的虚拟机,大多数是小规模和非主流的。而Xen和商业操作系统一样保持了相同的ABI。尽管它的确需要对操作系统进行修改,但修改可以尽可能的少。Denali虚拟化命名空间,而Xen认为在客户操作系统直接访问物理资源时,在虚拟机管理器中的“安全访问控制”就足以确保对物理资源的保护。 和其他商业虚拟机软件相比,Xen有很多独特的地方。比如它导出了一个新的轻量级事件机制代替了在x86架构中CPU和I/O设备之间的硬件中断,Xen的虚拟机管理器和各虚拟机之间的数据传输则采用了异步I/O环等等。关于半虚拟化技术和Xen实现更详细的内容,将在本书以后的章节中陆续介绍。 需要指出的是,随着CPU生产厂家对虚拟化支持的推广(如Intel的VT技术以及AMD的SVM技术),新版本的Xen已经能够支持这些新技术,采用CPU虚拟化支持所构造的虚拟机被称为硬件虚拟机(Hardware Virtual Machine,简称HVM)。在硬件虚拟机中,客户操作系统不需要修改就能直接运行。 (5)KVM KVM[Kvm.qumranet.com]是第一种成为传统Linux内核(V2.6.20)一部分的虚拟化技术,它为Linux系统提供了一种新的划分机制。其特点是系统内核通过添加内核模块使内核自身成为系统管理程序。并且,KVM向 Linux引入了一种除现有内核和用户模式之外的新的进程模式,这种新模式被称为客户模式,主要用来执行客户操作系统代码(至少是一部分代码)。KVM可以运行Windows和Linux虚拟机,每个虚拟机都有专用的虚拟化硬件,包括网卡、硬盘和显卡。虽然,KVM只能运行在Linux上,但它却具有内存管理和可扩展性较好等优点。 (6)用户模式的Linux 用户模式的Linux[Jeff Dike, 2000](User Mode Linux,简称UML)是一个开放源码的项目,它可以让用户在Linux上运行Linux系统。不同于以往虚拟机使用VMM直接架构在硬件之上,UML在操作系统和用户空间之上来进行实现。基本上,它在一个虚拟机上运行Linux就像在物理机器上运行一样,每一个执行都在用户模式。要做到完全在用户空间执行,必须能够在虚拟内核中拦截系统调用,UML的Linux ptrace工具可以跟踪系统调用,将在虚拟机中运行进程的系统调用转移到用户空间内核中执行。 (7)Cooperative Linux 与用户模式的Linux不同,CoLinux[Dan Aloni, 2004]通过改造Linux内核,将Linux移植到另外一个操作系统上(任何支持加载驱动的操作系统,如Windows),并使此Linux内核在内核模式下作为非特权的轻量级虚拟机运行。CoLinux和主机内核并行工作。然而,只有一个内核(主机内核)能控制物理物理资源,另一个内核(客户内核)只能获取抽象的虚拟硬件。其整体性能可以和UML媲美。 1.2.2.3 操作系统级虚拟化 硬件层次的虚拟机主要具有以下几个特性:高度的隔离性(虚拟机和底层物理机器均实现隔离)、易于让用户接受(和用户所习惯使用的普通机器看起来一样)、支持不同操作系统和应用程序而不需要重启机器、低风险和易于维护等。由于这一层次的虚拟机可以直接对裸机进行访问,从而导致用户在调试或运行应用程序之前需要花费大量时间来安装和管理虚拟计算机,其中包括操作系统安装、应用套件安装以及网络配置等等。如果用户希望虚拟机中所具有的操作系统和物理机器上安装的一样,并利用该虚拟环境来进行一些安全或沙盒测试等方面的实验,通过虚拟化的方式,可以有效避免对物理机器的重复安装,从而减少用户在机器安装上所花费的时间和精力。在本小节,我们将站在一个更高的层次(见图1-1所示)上来讨论虚拟化,以解决前面所描述的如何减少虚拟机中操作系统冗余的问题。这一层次的虚拟机和底层物理机器上的操作系统共享硬件资源,并在操作系统之上通过一个虚拟层(类似于VMware的虚拟机管理器)来展现给用户多个独立的、隔离的机器。 一个应用的操作环境包括操作系统、用户函数库、文件系统、环境设置等。如果应用系统所处的这些环境能够保持不变,那么,应用程序自身无法分辨出其所在的环境与真实环境之间的差别。操作系统级虚拟化技术的关键思想在于,操作系统之上的虚拟层按照 每个虚拟机的要求为其生成一个运行在物理机器之上的操作系统副本,从而为每个虚拟机产生一个完好的操作环境,并且实现虚拟机及其物理机器的隔离。在本节,我们简要介绍一些在设计中使用了该种抽象方法的虚拟机软件的例子及其所采用的相关技术。 (1)Jail Jail[P. Kamp & R. Watson, 2000]是一款基于FreeBSD的具有划分操作系统环境能力的虚拟软件。划分后的各个独立的操作系统环境称为Jail,每个Jail都包含典型的操作系统资源,例如进程、文件系统、网络资源等等,并且各Jail之间都具有很好的隔离性。Jail在原有chroot()的基础之上进行扩展,它不仅将文件系统的访问虚拟化,而且还将用户、网络子系统以及一些其它系统资源虚拟化。 Jail主要具有以下四个特点:采用目录子树的概念来限定各个Jail的访问范围,一旦进入到Jail中,进程就不能再访问该子树以外的对象;Jail可以通过设置有意义的主机名来简化系统管理员的工作;指定给Jail的IP地址在Jail的整个生命周期内都无法改变;可以通过Jail命令“监禁”进程以及其衍生的子进程。关于Jail的技术细节,感兴趣的读者可以查阅相关资料,这里就不再赘述。 (2)Linux内核模式虚拟化 另外一个类似的操作系统级虚拟化项目是专门为Linux定制的虚拟环境系统[Asplinux.ru]。这个系统的目标是允许管理员在一个单独的计算机上运行多个独立的应用程序环境,并且各环境之间具有适当的隔离性。虚拟环境(VE)包括一组独立的进程,这组进程拥有自己的文件系统、初始化和启动脚本等等。和Jail不同的是,它提供了更加良好的访问控制措施。例如,它可以使用户在虚拟环境内部拥有一部分管理权限。 (3) Ensim Ensim的虚拟个人服务器(VPS)[Ensim.com]技术将服务器的操作系统环境,分割成多个彼此隔离的系统环境来支持服务器的整合,从而达到减少成本、提高网站管理效率的目的。Ensim VPS通过虚拟一台服务器的操作系统来将其划分为一个个独立的称为VPS的操作环境。这些VPS相互之间独立运行。对于底层的操作系统来说,一个Ensim VPS就相当于一个应用程序。而对于应用程序来说,它又是一个和本地操作系统没有区别的操作系统。因此,从用户的角度来看,Ensim VPS就相当于真实的物理服务器。如图1-5所示为 Ensim VPS结构图。 VPS 5VPS 1VPS 2VPS 3VPS 4 应用程序 独立的 管理员/用户/组 独立的 网络/过程/文件 Ensim 虚拟化技术 主机操作系统 硬件 图1-5 Ensim VPS结构图 由于它允许管理员为每个VPS提供适当的硬件资源分配,比如内存、磁盘空间、CPU和网络带宽等,所以其实现的效果较前面所提到的系统要更好一些。这种虚拟技术同时也支持资源调整,比如,VPS可以完全透明的在物理机器之间进行迁移。 1.2.2.4 编程语言级虚拟化 传统机器通过ISA(Instruction Set Architecture)的支持来执行指令集。正是由于ISA抽象层的存在,使得在机器上运行的操作系统和程序相当于机器上的应用程序。硬件的操作通过专用的I/O指令(I/O映射),或者将一大块的内存分配给I/O,然后再操作内存(内存映射)的方式来进行处理。但无论如何,应用程序最终还是由一系列的指令所组成。随着Java虚拟机(JVM)的到来,使得这种新的实现虚拟机的方式逐渐引起人们的注意。这种抽象层次的虚拟化技术的主要思想是在应用层次上创建一个和其他类型虚拟机行为方式类似的虚拟机,并支持一种新的自定义的指令集(例如JVM中的Java字节码)。这种类型的虚拟机使得用户在运行应用程序的时候就像在真实的物理机器上一样,并且不会对系统的安全造成威胁。像普通的机器一样,它通过安装一个商业的操作系统或利用其自身的环境来为应用程序提供操作环境。这种抽象层次的虚拟化系统主要包括Java虚拟机、Microsoft .NET CLI、Parrot等。 (1)Java虚拟机 在Java语言中,其后端实现了一种新的指令集的编译器。正是由于这样的一个后端使得Java成为一种与平台无关的语言,能够在包括Windows、Unix、Mac以及其它流行的操作系统上运行。这个后端又被称为Java虚拟机[Bill Venners, 1996],简称JVM。JVM是一种执行Java字节码(byte code)的虚拟机。这些代码通常由Java编译器生成,需要在JVM上执行的程序必须被编译成由字节码组成的标准的二进制形式,即.class文件。这些二进制文件再由JVM runtime解释执行。除此之外,JVM还为Java字节码提供了一个操作环境,因此,Java平台其实是Java虚拟机和Java操作环境(JRE)的结合。因为JVM最终通过一些底层语言来实现,因此它可以提供比传统机器更好的灵活性。 JVM是一个支持线程的基于堆栈的结构。在JVM中,每个线程都有它自己的程序计数器和虚拟的寄存器集(JVM支持的寄存器)。它支持的指令包括加载/存储、算术、类型转换、对象创建/操作、入栈/出栈、分支、调用和异常处理等等。但是,为了实现Java核心API到主机操作系统之间的映射,并保证其兼容性和高效性,其涉及的内容并不仅仅只是字节码的模拟。 JVM支持4GB内存空间、32位寻址方式和32位虚拟寄存器。其虚拟硬件可以分成四个基本部分:寄存器、堆栈、垃圾回收和方法域。这样的一种虚拟机架构能够对操作进行细粒度控制,并且能够安全执行来自远程的不可信代码,这种模型的典型应用包括Java小应用程序等。这种虚拟化方案具有安全、易调试、平台独立性等几个重要特性。因为所有的硬件设备都在JVM所处层次之下,它能够访问系统所有资源以及虚拟执行通常应用程序所能做的一切事情,因此,Java语言具有和传统语言(比如C和C++)一样强大的功能。 (2)Microsoft .NET CLI .NET框架中的CLR(Common Language Runtime)公共语言运行时是微软版的通用语言基础设施(CLI)[Microsoft, 2002]规范,其作用与JVM类似。CLI是一个支持动态组件编程模型的多层架构,它是一种标准化的语言扩展(对标准C++进行扩展)。在这样的一个环境中,它能够实现库和语言之间紧密的协调工作。和Java框架一样,它也提供接口、类和对象。它同时为使用这个平台的所有语言都定义了一个通用的库接口。其源代码也被编译器转化为一种中间的形式,然后再由CLR执行。 (3)Parrot Parrot [Parrotcode.org]是为支持Perl6语言而新设计的解释器。它被设计成一种独立的虚拟机,可以用来执行从Perl5, Perl6等动态语言(dynamic languages)编译而成的字节码。 1.2.2.5 程序库级虚拟化 在几乎所有的系统中,应用程序的编写都使用由一组用户级库来调用的API函数集。这些用户级库的设计能够隐藏操作系统的相关底层细节,从而降低普通程序员的软件开发难度。 这部分所谈论的例子都工作在操作系统层上,并且创造了一个与众不同的虚拟环境,在底层系统上实现了不同的应用程序二进制接口(ABI)和不同的应用程序编程接口(API)。这种技术能很好的完成ABI/API仿真工作。 (1) WINE Wine[Winehq.com]代表“Wine Is Not an Emulator”,即它不是一个模拟器。它的目的是使主机在没有Windows 操作系统的情况下能够运行 Windows 程序。认为Wine不是一个模拟器,因为它不对处理器进行模拟,并且不能在其上安装操作系统或设备驱动程序。但是,Wine集成了Windows APIs,并且可以作为库将Windows应用程序移植到Unix上。然而从某种角度,我们也可以把Wine看作是一个模拟器,因为它对于Windows二进制代码文件(.EXE文件)而言,就相当于Windows,并且严格仿真Windows的行为。换句话说,Wine是在Unix上层用来调用Windows API/ABI的一个虚拟层,这样就实现了在Wine上可以运行Windows二进制代码。 (2)WABI WABI[Sun.com]的全称是Windows Application Binary Interface(Windows应用程序二进制接口),它是Sun的一种实施方案,其目的与Wine类似。它通过使用X Windows系统使用户能够在几个UNIX 操作环境上运行Windows应用程序。其另外一个变种称为WabiServer。WabiServer可以实现多个用户的远程连接以及在客户端上使用Wabi。它通过将Windows调用转换成X Window和Unix 调用,在RISC平台上,将x86指令翻译成RISC指令的方式来进行工作。但是,由于其实现的范围没有Wine广泛,因此导致某些程序在该环境下并不能正常的执行。 (3) LxRun LxRun[Steven Ginzburg, 2001]是一个为其他x86 *IX机器,例如SCO OpenServer、SCO UnixWare和Sun Solaris 等设计的Linux x86二进制仿真器。事实上,Linux和iBCS2二进制文件之间并没有多大区别,主要区别在于处理系统调用的方式上。在Linux中,要使用一个“int 0x80”指令来跳转到Linux内核中系统调用处理的部分。而在其它系统中,这个“int 0x80”通常产生一个SIGSEGV信号,LxRun拦截这些信号并依照Linux程序的需要发出一个类似系统调用的请求。这样做的结果就是Linux二进制文件在LxRun的帮助下可以以很小的性能代价来运行。而完成所有这些工作都无需修改Linux内核或其二进制文件。 (4)Visual MainWin 基于UNIX和Linux 的Visual MainWin[Mainsoft,whitepaper]是企业级应用平台,它使得软件开发商能够将在Windows上使用Visual Studio开发的C++应用程序部署在UNIX和Linux操作系统上。其核心思想是利用UNIX 编译器重新编译Windows源代码来创建本地UNIX应用程序。Visual MainWin运行时包括UNIX上的Windows运行时和核心服务。基于UNIX和Linux的Visual MainWin核心服务提供的功能包括同步对象、线程等等。 1.3 虚拟化的相关研究内容 到现在为止,我们已经介绍了虚拟化的概念、特点和作用,并讨论了虚拟化技术发展过程中作为指导的核心内容。尤为重要的是,这些是本书介绍计算系统虚拟化的基础所在。接下来我们将探讨计算系统虚拟化涉及的更多的相关技术和研究内容。包括多计算系统的虚拟化、用户使用环境的虚拟化、虚拟化系统的安全可信问题和虚拟计算系统的性能评测的理论与方法等。 1.3.1 多计算系统的虚拟化 多计算系统虚拟化涉及到的研究内容非常广泛,研究范围扩展到几乎所有的多计算系统领域。由于虚拟机的加入带来的新计算模式的影响,使得多计算系统虚拟化必须针对个性化需求,高效组织计算资源,隔离具体的硬件体系结构和软件系统之间的紧密依赖关系,使用户可以获得高效、透明、普适、安全的服务。 从现有的多机环境虚拟机研究状况来看,为解决计算系统体系结构的紧耦合特性与多粒度资源使用需求之间的矛盾,首先凸显出了多计算系统的动态构建问题。如何从系统结构的角度,按照应用任务的需求,将资源进行共享和动态划分,以便于动态建立起基于多核的虚拟计算机或者基于分布式计算资源的虚拟计算环境,这尤为重要。而由于系统可被多个用户同时使用,如何协调多个用户的请求,优化系统性能、降低系统运行成本也就成为动态构建技术的主要研究内容。值得指出的是,为了达到先进的计算环境特性,支持更加广泛的应用,虚拟机的迁移问题在动态构建论题上成为了集中关心的焦点。虚拟机的迁移分为动态迁移和静态迁移,动态迁移在将虚拟机中运行的操作系统与应用程序从一个物理节点迁移到另外一个运行节点的过程中,保持客户操作系统和应用程序的继续运行而不受干扰因此,更能够实现服务器之间保持负载均衡、保证服务质量、节约电能等诸多优秀的特性。目前,很多机构都在研究新型系统级虚拟化架构和虚拟计算系统动态构建的理论及优化方法。VMWare公司开发的Virtual Center是一套虚拟架构的管理软件,管理员能够通过它管理虚拟机池[C. A. Waldspurger, 2002]。针对Xen虚拟机也有一些管理软件,英国剑桥大学在Xen的基础上实现了虚拟机迁移机制。斯坦福大学的Cellular Disco[K. Govil et al., 1999]能够在一个NUMA(Non Uniform Memory Access Achitecture)主机上虚拟若干个SMP(Symmetrical Multi-Processing)系统,它通过对虚拟CPU采用“gang-scheduling”调度策略,避免延迟相关的性能下降,但是它并不适用于跨物理主机的集群系统。 同时,有不少机构研究了虚拟机在分布式环境下的应用。剑桥大学基于Xen的Parallax项目可以管理大量虚拟机,消除写共享,增加客户端缓存,利用模版映像来构建整个系统。Ventana系统利用集中存储来保证虚拟服务的多版本、隔离性和移动性。美国Florida大学的研究人员首次提出将传统虚拟机应用于网格等分布式环境下,并提出了基于虚拟机的网格服务体系结构。目前,国际上基于虚拟机的分布式计算已经成为了研究的热点[A. Whitaker et al., 2004; M. L. Massie et al., 2004]。 相对于单一计算节点来说,由多个节点构成的多计算系统的管理是一个挑战。因为其管理难度不再是对虚拟机和实际机器的识别和管理,而是如何在更大规模的系统上实现更多的虚拟机,以更出色的整合能力使用户通过简单的操作界面统一管理几个数据中心的资源。用虚拟化的方法,为了解决这个问题,引入了多虚拟机的单一映像方法,使得多个计算系统资源看起来就像一个单一的计算对象,从而将多计算系统转化成单一计算系统的问题。目前,许多科研机构研究了在多机环境下的虚拟单一映像系统。东京大学的Kaneda等实现了一个具有上述功能的VMM,它针对x86体系结构,实现了对CPU、内存和I/O设备的模拟。该VMM在8台物理主机上建立了一个8路的SMP虚拟主机,并在其之上成功安装了Linux-SMP操作系统。但是由于基于多物理机的结构,上层操作系统无法知道底层的某些信息,性能提高有限。新南威尔士大学的vNUMA项目采用虚拟机技术在2个安腾体系结构的物理结点上虚拟一台cc-NUMA(Cache Coherent-Non Uniform Memory Access)计算机系统,并使用特殊的Linux版本来作为操作系统。但是,vNUMA仅支持两个物理结点,扩展性不理想[M. Chapman & G. Heiser, 2005; D. Thain et al., 2005]。 需要指出的是,目前针对多计算系统资源虚拟化的研究仍在积极进行中,就目前来说做到的极为有限。比如现有的多机虚拟化技术只是将多个虚拟机聚集在一起,实现虚拟机在多机环境下的直接应用,并且在此之上完成了中央控制管理,没有达到有机整合的目的。在这个基础上,继续研究的工作可以将更多的精力集中到将虚拟机和虚拟网络整合在一起,克服现有多机系统管理软件依赖于特定操作系统的弱点,形成一个让用户能够动态构建虚拟运行环境的多机系统管理模式。另外,现有的分布式共享内存管理在用户层实现,应用程序在使用的时候,需要改变原有的编码,以便能够使用分布式共享内存,这一要求还无法达到高效透明的目的。因此,为了达到高效透明的目的,需要在内核模式实现分布式共享内存模型,并且克服现有多机整合的性能瓶颈,使得虚拟机管理器和操作系统相互配合[A. Warfield et al., 2005; P. Nath et al., 2006]。 1.3.2 虚拟用户使用环境 前面所述的内容大多是服务器虚拟化技术,而虚拟化技术的根本性目的,是为了提高普通用户对计算机的操控力,降低计算机使用的服务性,最终提高利用效率。虚拟用户使用环境是指将虚拟化的理念、技术广泛应用于桌面环境、用户操作环境,建立一套可移植、可重构、按需定制的可视化用户使用环境和程序执行的自动配置环境,以适应软硬件环境和任务需求的变化,协调分布呈现的计 算资源,最终建立任务执行的协同计算环境。由此看出,建立虚拟化的用户使用环境是一项综合性课题,涉及到桌面虚拟化技术、应用程序的虚拟化、网络虚拟化和虚拟化编程环境等。 桌面虚拟化改变了传统的计算机管理方式,利用虚拟化技术对操作系统及应用程序进行集中的管理和高效的分发迁移,使得用户在任何时间、任何地点,只要具备基本的硬件就可以使用自己需要的工作环境。应用程序虚拟化则可以把应用程序从操作系统中解放出来,实现自给自足的虚拟运行环境。在成功实现这种分离后,还产生了很多优化技术,如将应用软件流水化包装起来,应用软件无需完全安装,只要一部分程序能够在电脑上运行即可。 在网络虚拟化方面,虚拟计算环境需要支持网络资源和虚拟组织资源的有效聚合和可信协同。目前虚拟机网络项目仅关注虚拟机网络的运行支持,而缺乏对虚拟机网络的设计、部署、修改等静态层面的支持,用户不能方便地定制虚拟机网络。 除此之外,虚拟化技术还逐渐运用在应用程序分发,程序语言优化,不同程序语言之间的功能共享等方面。例如Java虚拟机和公共语言运行库就通过语言虚拟机技术,实现更有效的内存管理、安全校验、语言抽象等机制。 当前,该领域研究人员已经开展了一些卓有成效的研究工作。传统技术,如Java的JVM、C#的CLI等,其本质就是一种程序级的虚拟使用环境。而YouOS和eyeOS这类基于JavaScript与AJAX技术的Web操作系统更是在桌面工作环境虚拟化方面走在了其它虚拟化技术的前列[S. Adler, 2005]。其基本思想是基于Web技术,将用户的各类应用虚拟化、远端化,从而使得用户的工作环境可以自由的迁移和定制,真正实现用户桌面的虚拟化。卡耐基梅隆大学和Intel合作的ISR(Internet Suspend/Resume)项目基于虚拟机技术实现了用户计算环境的可迁移。人们的日常工作都在虚拟机中进行,上下班或外出时,只需挂起虚拟机并保存,就可通过便携设备或网络把完整的工作状态传送至目的地,只要在目的地的任何一台计算机上重新加载虚拟机,用户就可从挂起时刻的状态开始继续工作。斯坦福大学的Collective项目[R. Chandra et al., 2005]研究基于虚拟机技术的虚拟计算设备,可由专业人员根据各种应用需要配置计算环境,并采用各种优化方法以最小的存储和传输代价维护在用户计算机上的缓存版本,用户可根据需要选择使用不同的虚拟计算设备。 以上各项目充分显示了虚拟化的用户运行环境已经成为当前的一个非常重要的研究热点。但是,系统的透明性、用户接口的平台无关性、用户需求的随处可满足性仍无法充分做到。用户还是不得不与各类不同的用户接口、系统直接打交道,工作效率不能有效地提高。如何构造一个真正的可移植、可重构、按需配置的普适运行环境尚在进一步的研究中。 1.3.3 虚拟计算系统的安全可信机制 虚拟化技术在带来诸多好处的同时,也为系统安全引入新的潜在问题,需要相应的方法以最大程度降低可能潜在的安全威胁。归结起来,虚拟化系统的安全挑战主要有以下两个方面:一方面是计算系统体系结构的改变。虚拟化技术已从完全的物理隔离方式发展至共享式虚拟化,实现计算系统虚拟化需要在计算性能、系统安全、实现效率等因素间进行合理的权衡。这种过渡下,虚拟机监视器和相关具有部分控制功能的虚拟机成为漏洞攻击的首选对象,使之成为最重要的安全瓶颈。并且,现有虚拟化系统通常采用自主访问控制方式,难以在保障虚拟机隔离的基础之上实现必要的有限共享。另一方面,计算机系统的运行形态已经发生改变。虚拟计算允许用户通过操纵文件的方式来创建、复制、存储、读写、共享、移植以及回滚一个机器的运行状态,这些虽然极大地增强了使用的灵活性,却破坏了原有基于线性时间变化系统设定的安全策略、安全协议等的安全性和有效性,包括软件生命周期和数据生命周期所引起的系统安全[T. Garfinkel & M. Rosenblum, 2005]。 目前在程序级虚拟使用环境的安全保障方面已有相应的研究与应用,典型代表就是Java安全虚拟机。它提供了包括安全管理器和Java类文件认证器等多种安全机制,安全管理器提供加在应用程序和特写系统上的安全措施,Java认证器在.class文件运行前完成该文件的安全检查,确保Java字节码符合Java虚拟机规范。针对操作系统虚拟化的安全问题,基于Windows操作系统的Microsoft虚拟机(Microsoft Virtual Machine)能阻止恶意用户对Java applet访问COM对象、调用JDBC等安全漏洞的攻击。 在虚拟机的安全验证方面,最典型的代表是美国密西根大学的Peter Chen和Brian Noble研发的ReVirt系统,它通过采用虚拟机技术提供独立于操作系统的安全验证功能,ReVirt能提供足够信息逐条回放虚拟机上执行的任务,通过建立具有各种依赖关系的攻击事件链,重构出攻击细节,ReVirt采用了反向观察点和反向断点技术针对虚拟机上的恶意攻击进行和回放,提供验证功能[G. W. Dunlap et al., 2002]。 除了上述研究之外,基于虚拟机的入侵检测技术也作为与虚拟机技术相辅相成的手段发展起来,在运行虚拟机的宿主主机平台上建立入侵检测系统,为网络系统的安全提供了保障。在入侵检测技术中,传统的蜜罐技术和蜜网技术也都可以通过虚拟化技术实现,是目前基于虚拟机的入侵检测系统的主要应用。 综合而言,当前开展的虚拟机安全性研究大多都针对某一个安全问题进行,系统性的分析与研究仍在不断探索。 1.3.4 虚拟计算系统的性能评测 从前面所讲述的相关技术内容来看,虚拟计算系统已经越来越多地为一些重要的商业应用提供了行之有效的解决方案。这些解决方案在带来更多复杂性和更多性能开支的同时,使得针对虚拟计算系统的性能评测变得尤为重要。一个计算系统是否适合部署虚拟化技术,是否部署了合适的虚拟化技术,又或者部署了虚拟化技术后是否使平台达到最优化,这均需要有相应的性能评测理论和方法来进行衡量。 虚拟计算系统的评测内容包括系统性能和可用性评测等。目前,可用于虚拟计算系统性能评测的方法主要是借鉴传统计算系统已有的性能评测方法:测量方法、模拟方法和分析方法。测量方法通过运行涉及不同类型计算的基准测试程序(Benchmark)评测系统的计算能力,比较著名的测试程序有Linpack、NAS、ParkBench、 SPEComp、Perfect、SPLASH等。模拟方法通过构造系统模型和工作负载模型来近似目标系统,进而了解目标系统的特性,一般可采用专用的模拟语言描述(如ECSS, CSS)和一些模拟工具。分析方法通过为计算系统建立数学模型,进而在给定输入条件下通过计算获得目标系统的性能特性[V. S. Adve & M. K. Vernon, 2004; S. Chen et al., 2005]。目前,主要集中在基于排队论的性能分析研究,如随机Petri网、Markov排队网络、混合排队网络等。然而,计算资源的虚拟化和计算资源聚合的动态化使传统计算系统的评测研究方法并不能完全适应虚拟系统的评测,需要面向计算资源虚拟化和动态构建特征,逐步确立适合自身的虚拟计算系统评测理论与方法。 在虚拟机的性能分析方面,主要有基于“黑盒”的性能测试,通过运行针对不同应用特性(如数据库应用、文件系统、WEB应用等)的性能测试软件来评测虚拟机系统性能。目前还不存在公认的测试集和标准。在基于分布计算资源虚拟系统的性能研究方面,主要集中于计算任务的性能监测、分析和预测。目前已有一些针对这类系统的性能监测与预测工具,但这些工具主要集中于对系统性能一个或少数几个侧面的监测和分析,缺乏综合性的性能监测手段,同时将性能监测及分析结果应用于系统调优和调度的研究较少。因此,在进一步研究中,需要针对不同计算性质的任务模式、应用测量方法和统计分析技术,研究典型虚拟机不同技术途径在性能上的表现特征及性能瓶颈,分析提高性能的调优策略。 在虚拟计算系统可用性的测试技术方面,其研究与开发也还处于刚刚起步阶段,尚无成熟的测试方案和基准测试程序,如Berkeley针对他们研制ISTORE 系统开发了一套用于测试可用性的基准测试程序。 综合看来,目前虚拟计算系统性能的研究主要集中于虚拟机或计算资源聚合系统的性能测量及监测,而在虚拟系统性能模型研究以及利用性能监测结果对系统调优和动态调度的研究还很少,计算系统可用性评测研究也才刚刚起步。 1.4 虚拟化的应用 虚拟化技术的本质及相关研究内容在前面小节中已作了铺述。这一节中,我们关注虚拟化技术的重要应用领域——建模与仿真技术与高性能计算。在现状研究中,建模与仿真技术与高性能计算一起都已形成自己的综合技术体系,正成为继理论研究和实验研究之后第三种认识、改造客观世界的重要手段[李伯虎等,2004]。然而随着计算机系统规模越来越大,计算资源数量及种类越来越庞杂,仿真资源利用率不高,仿真系统搭建难度大,仿真运行可靠性不够等问题,需要借助、结合虚拟化的方法以提供解决思路。经过一段时间的发展,建模与仿真技术与高性能计算可能的应用模式与前景都极大拓展。高性能计算领域的应用前景扩展到包括虚拟系统环境、系统调试、异构平台整合、旧版本应用兼容、定制OS、提高系统可靠性、安全性等。虚拟化仿真技术也已经逐步深入到包括航空、航天、武器、电力、交通等关系国计民生的重要领域之中,成为实验分析与决策验证的重要手段。 1.4.1 虚拟化在高效能计算机中的应用 目前,虚拟化技术被应用于高效能计算领域尚不广泛,两者结合的应用也并不多,多见于集群和网格方面。分析其原因主要有两点:其一,虚拟化带来的开销对于那些对某部分性能非常敏感的高效能计算应用程序来说难以接受,比如VMM需要干涉每个特权操作。其二,传统的VMM所构造的VM所能够利用的资源例如CPU、内存、磁盘、通信带宽等通常只面向单一的物理节点。很多研究者认为只有在突破这种所面向资源的局限性,或者说实现部件级的虚拟化,高效能计算才能充分从虚拟机技术中获益。尽管如此,随着虚拟化技术的深入研究和高效能计算领域的发展,特别是在底层硬件越来越多的加入虚拟化的支持,以及高效能计算机体系结构向 多层次、多粒度的异构化方向发展以后,高效能计算领域的诸多难题都有了新的解决方法。 在高效能计算机领域,使用现有的某一种体系结构越来越难以应对应用需求的多样性和广泛性。随着高效能计算机系统性能的不断提高,在其上运行的许多实际应用运行效率偏低,异构的高效能计算机体系结构,是可能解决该问题的途径之一。但是,异构系统大大增加了系统的复杂性,需要虚拟化技术屏蔽结构特征,以保持系统的可用性,特别是应用程序的可移植性和编程模型的一致性。高效能计算机制造商Cray提出的自适应超级计算(Adaptive Supercomputing)设想就融合了虚拟化的思路,并开辟了Cascade异构系统。Cray采用集成的方法来组织异构计算,综合利用多种类型的处理技术,把标准的微处理器(标量处理)、向量处理、多线程和硬件加速技术都整合到同一个高效能计算平台上去。通过这种方式,系统自动适应用户代码,使得系统能够在同一个高效能计算平台上执行范围宽泛的应用程序,用户不必再为了在能够某个特定系统更有效地运行而修改应用程序。此外,这类异构系统还有日本理化学研究所的京速(10PFlops)系统和 IBM的RoadRunner系统等,它们从不同的角度尝试着多种虚拟化技术在高性能计算机上的应用[A. Sundarara et al., 2005]。针对性能开销和管理效率问题,目前Ohio State大学和IBM也提出了一个框架,可通过VMM bypass I/O技术和可扩展VM映像管理技术来解决。 在大规模的高效能系统的容错方面,基于虚拟化技术实现的一种主动容错机制具有积极意义。该机制不只依赖于传统的检查点的保存与恢复策略,更能够自动、透明地让进程从一个节点迁移到另外一个更好的节点。目前,基于Xen的容错机制通过预迁移方法,在MPI任务迁移时可以不中断任务本身的执行;基于OpenIPMI的health监控机制具备预测未来的节点失效事件的能力;基于Ganglia的负载平衡可以利用资源监控数据,选择一个目标节点进行VM迁移,它可以是具有最小系统负载的节点或是通过更多的检查来确定。 在并行程序设计领域里,科学计算应用程序的编写渐趋复杂,特别是学科交叉的应用程序编写困难。然而,基于虚拟化技术的并行编程模型使得这一难题有了新的解决方法。比如,程序员可以将程序分解成大量可并行处理的虚拟实体,每个虚拟实体对应一个虚拟处理器。程序员不需要显式地关心物理处理器的使用,而只需要考虑各个虚拟实体之间的交互。基于虚拟化技术的并行编程系统也能为高效能计算提供更灵活的任务映射、迁移和动态平衡方式。 另外,美国橡树岭国家实验室的Christian Engelmann等人在虚拟环境的基础上提出了虚拟系统环境[Engelmann et al., 2007]的概念。与虚拟环境不同的是,虚拟系统环境是基于系统级hypervisor虚拟化技术实现的,不仅能够为科学计算应用程序的开发和部署提供沙盒环境,更可用于系统软件的无缝开发、测试、和部署过程,在系统层实现了从台式电脑到集群再到千万亿次计算机的 “即插即用” 超级计算。 除了提出虚拟系统环境,美国橡树岭国家实验室为了扩展虚拟化技术在高效能计算方面的应用,更开发了一组用来创建和管理高效能计算 cluster的工具包——OSCAR-V。它已经支持了系统级虚拟化技术Xen和QEMU,并且增加了其最初版本OSCAR 集群中创建和管理VM的工具V2M。此外,基于虚拟计算环境进行配置和管理也应用到了网格中,典型的应用是Virtual Workspaces项目和Virtuoso项目。 虚拟化在高效能计算中应用的范围越来越广,然而一些研究者仍然认为基于半虚拟化技术并不适用于高效能计算领域,其原因还是半虚拟化引入的性能开销问题。然而,有部分研究者通过分析半虚拟化技术应用于高效能计算的测试数据得出了不同的结论,认为通过进一步改进和优化实现技术,半虚拟化技术完全可以在高效能计算机上取得很好的应用性能。本文后续章节将具体讲述这些用于对比的测试过程及数据。 1.4.2 虚拟化仿真技术的应用 虚拟化仿真技术的发展建立在已有的建模仿真技术和虚拟化技术基础之上。半个多世纪以来,仿真软件/环境的发展一步步交叉推进,大致分为五个发展阶段:仿真程序包和仿真语言、一体化仿真环境、智能化仿真环境、面向对象的仿真及分布式交互仿真。近年来,该领域研究的热点很多,如网络化建模仿真技术、智能系统建模及智能仿真系统、复杂系统/开放复杂巨系统的建模/仿真技术、虚拟样机工程技术、基于普适计算技术的普适仿真技术等,取得了众多研究、应用成果。然而,随着仿真应用的不断深入,尤其是面对越来越庞大的仿真系统规模以及数量与种类越来越多的计算资源,传统仿真技术的不足之处愈发明显,结合虚拟化技术的“计算系统的动态构建”、“ 计算资源使用高效透明”、“计算环境的协同普适”等特点而发展而来的虚拟化仿真,成为建模与仿真技术发展的一个重要热点。 虚拟化仿真是以相似原理、模型理论、系统技术、信息技术以及建模与仿真应用领域的有关专业技术为基础,以计算机系统、与应用相关的物理效应设备及仿真器为工具,利用模型参与已有或设想的系统,结合虚拟化技术的最新进展,实现仿真系统的按需动态构建,异构仿真资源的透明使用以及仿真运行环境的协同普适。归纳起来,基于虚拟化仿真技术搭建的复杂产品仿真系统就具应当具 有三个特点:一,仿真系统的按需动态构建。复杂产品仿真系统说到底还是基于复杂应用的分布计算系统,因此,依赖于虚拟化技术可伸缩的计算系统框架,虚拟化仿真系统能够按照实际仿真应用需求,动态构建相应的仿真系统。这里面还包括快速部署。二,异构仿真资源的透明使用。随着软件环境的不断发展,仿真资源,尤其是软件资源的重用性问题加剧。虚拟化仿真系统中的虚拟机加载软件模型所需的系统环境,完成了对于仿真模型的良好封装,从而使得我们可以十分便捷、透明地实现仿真资源的重用。并且由于这种对仿真资源的良好封装,虚拟化的仿真资源协同管理器通过对仿真任务的监控调度以及负载平衡的动态管理,可以有效地保证仿真资源的高效使用。三,协同普适的仿真运行环境。传统的复杂产品仿真系统与用户交互的较少。而在虚拟化仿真系统中,由于系统具有以上两种特点,用户可以根据自己的需求,快速部署好想要的仿真系统,并个性化地订制自己所要的仿真结果与数据。 目前,在复杂产品仿真、网络安全仿真、粒子仿真等诸多领域都出现了一些较好的系统,它们在不同程度上引入了虚拟机,并解决了一些现有的问题。这些问题集中在对于异构资源的管理与调用,计算资源利用率的提升,以及仿真安全性的考量。国内总装备部军仿专业组“十五”重点项目所支持的基于JVM的起落架协同仿真系统,涉及机械、控制、液压等不同的专业领域,是一个复杂机电液系统。它基于仿真网格COSIM-Grid 1.0v构建系统,可以实现仿真模型的异地共享与协同,同时利用JVM技术,屏蔽了底层多学科仿真模型资源的异构性,解决了资源与系统的无关性问题。美国Wisconsin高级网络实验室(WAIL)研究开发的用于Botnet网络研究的综合试验台环境仿真系统[Paul Barford & Mike Blodgett, 2007],通过每个VM上运行一个bot(能够按照预定义的指令执行操作,具有一定智能的程序),扩大了botnet的规模。并且基于虚拟机的快速部署机制和OS/bot映像库初步实现了bot运行环境的自动化部署。CERN的ATLAS实验中的粒子探测器仿真系统基于VMware ESX构建,提高了仿真运行的安全隔离性,且计算资源的利用率处在一个较高的水平。 目前的虚拟化与仿真技术的结合尚处在研究的初步阶段,存在进一步融合和发展的空间。首先,虚拟化的仿真系统体系结构的研究作为系统地开展相关研究的基础,随着虚拟化技术的深入将不断丰富。其次,前文指出在对于异构资源的管理与调用方面,虚拟化已经为仿真系统提供了一些解决方法。然而,目前的资源描述方式并没有考虑虚拟化后的资源特点,没有针对虚拟化的仿真资源进行优化。在虚拟化的仿真资源层的基础上,还需要相应的仿真中间件,来管理、配置、支撑和调度,以增强仿真资源的统一化管理的力度。另外,多样的仿真模型资源需要建立多样的仿真设计环境和仿真运行环境。大规模、复杂甚至重复的部署工作,增加了仿真系统的成本,也不利于扩大仿真系统的规模。而在虚拟机的快速部署机制的支持下,复杂的软件环境将精简为一系列配置文件和一套磁盘 映像,部署工作将变成相对简单的文件拷贝与恢复,甚至可以自动化此过程。这也将为用户按需动态定制的个性化仿真执行环境打下基础。除此之外,虚拟化技术的引入为仿真运行管理在仿真资源动态使用、仿真任务监控和调度、容错迁移、动态负载平衡等方面带来便利。比如基于虚拟机的在线迁移和容错技术,现代仿真系统中可以实现动态的仿真网格容错迁移机制,屏蔽应用层在调用各种仿真资源中的计算错误、死机、负载不平衡、间断连接等问题,保证了仿真应用系统有效、可信、健壮的运行。 1.5 各章内容简介 本章引入了很多将会在本书中展开的概念。虚拟化技术存在于计算系统的不同层次,而不同层次的虚拟化技术,除了其实现手段有相通之处外,相互之间又互相依赖和互相融合。需要指出的是,虚拟计算的真正潜力在于对计算资源的管理,而并不能直接提高计算机性能。 第2章的主要内容是有关指令级虚拟化的介绍。二进制翻译技术是贯穿这一章的核心,讨论的内容包括二进制翻译系统的框架和动态优化问题,以及面临的技术难点。在第2章中,我们将看到二进制翻译技术研究中几个典型系统的分析。这些实用的方案能让我们更好地理解指令级虚拟化方法的设计与实现。在以后的每一章中,我们也尽量结合相关的实例作为叙述原则。 第3章主要介绍计算系统虚拟化的方法,着力于系统级虚拟化方法的详细讨论。资源(CPU、内存和I/O设备)虚拟化方法是帮助理解虚拟化技术的指导,一些在大多数章节中要使用的重要概念将在本章出现,包括全虚拟化、半虚拟化技术以及硬件辅助虚拟化技术等。这一章讲述的例子涵盖了目前较流行的系统级虚拟化解决方案,重点放在它们不同的系统结构和实现方法上。作为后续章节论题的桥梁,第3章也包含几个小节将讲述操作系统适配技术、进程级虚拟化和语言级虚拟化等论题。 第4章讨论了多虚拟机监控与管理所涉及的各项技术。虚拟机的迁移和单一系统映像是针对多计算资源虚拟化管理的两个重要方面,本章主要介绍了虚拟机的迁移。同时,这一章还讨论和分析了国内外最新的多计算系统虚拟化方面的研究成果,涉及多计算系统资源的动态构建、服务器合并技术等多计算系统资源环境下的应用问题。 第5章从实用化的角度介绍虚拟化用户使用环境的研究动机、研究现状以及核心问题。虚拟化用户使用环境是更贴近于普通用户高效地使用计算资源的一个领域,考虑到这一点,本章对虚拟计算系统普适化运行环境下的几个细分领域(桌面虚拟化技术、应用程 序的虚拟化、网络虚拟化和虚拟化编程环境)都选取了典型系统进行详细讲述。 第6章讲述虚拟化系统的安全可信问题。本章首先分析了虚拟化系统与传统系统相比较下的诸多安全挑战,重点介绍并分析主流虚拟化技术中所采用的基本安全机制和可信机制,进而从多方面对虚拟化系统的安全可信进行了讨论。同时,虚拟化技术与入侵检测的相互结合与应用,恶意代码的检测与隔离技术等也是本章涉及的内容。 第7章围绕着虚拟计算系统性能评测展开讨论。详细介绍了性能测量的指标、方法、规范,以及性能分析中的各种模型,包括在虚拟计算系统构建不同的模拟器来实施性能评价的多种方法。本章最后给出了传统和虚拟计算系统的可用性综述,在分析研究现状的基础上,结合虚拟计算系统的特点,总结了虚拟计算系统的性能评测的理论与方法。 第8章和第9章的目的是从应用的角度来介绍虚拟化技术。第8章首先分析了现有的虚拟化技术应用到高效能计算领域时需要解决的问题和需要研究突破的技术。然后,把重点放在讨论虚拟化技术在高效能计算领域已经开辟的一些成功的应用和管理工具。另外,本章还介绍了国外研究人员对半虚拟化技术应用于高效能计算进行的性能测试结果和分析结论。 第9章讨论了虚拟化仿真技术的各种应用。这一章开头针对建模仿真技术,其在高性能计算资源整合中遇到的问题,复杂产品仿真目前需要解决的实际应用需求做出分析。然后,详细阐述虚拟化仿真系统的特点,体系结构以及关键技术。由于虚拟化仿真的应用在复杂产品,国民经济,安全,军事,高能物理等领域都发挥着独特的影响和作用,本章的最后针对这些论题也分别进行了讨论。 本书的第10章讲述国内外虚拟化技术的研究现状和发展趋势。 第二章 指令级虚拟化 一般说来,计算系统的虚拟化可以在硬件、指令集、操作系统、库以及高级语言等五个不同的层次上实现[Smith,2005]。目前流行的许多虚拟化技术,如以Xen为代表的部分虚拟化、以VMWare为代表的全虚拟化、以Intel VT和AMD Pacifica为代表的硬件虚拟化、以及最近才被提出的预虚拟化等,通常在硬件或操作系统层面上实现,旨在解决如何将多种不同的软件支撑环境(如操作系统)集成在特定硬件平台下这一问题。而在指令集层次上进行虚拟化,能够使同一系统程序或应用程序运行在不同结构的硬件平台之上,扩大了这些虚拟化技术的应用范围。因此,指令级虚拟化技术是其它虚拟化技术的必要补充,也是计算系统虚拟化技术不可或缺的关键部分。 在指令集层次上实现虚拟化,实际上就是将某个硬件平台上的二进制代码转换为另一个硬件平台上的二进制代码,从而实现不同指令集间的兼容,这一技术也被形象地称作“二进制翻译(Binary Translation)”。 二进制翻译技术最初被用于模拟新的计算机体系结构,执行没有源程序的二进制代码,辅助用户从一种体系结构/操作系统向另一种体系结构/操作系统迁移。随着Java语言的出现,这项技术在即时编译中得到应用,将Java虚拟机的字节码在即将执行前翻译为目标主机的可执行代码。此外,动态二进制翻译技术还被用于构建体系结构模拟器以及动态优化系统等。本章将结合国内外的研究工作系统地讨论这项技术并分析其发展趋势。 本章共分五节:2.1节介绍二进制翻译系统的基本结果,包括二进制翻译的实现方法、二进制翻译系统的框架和动态优化问题等;2.2节介绍实现二进制翻译时面临的技术难点,并分析二进制翻译过程的时间开销;2.3节介绍二进制翻译技术研究中几个典型的研究成果,以展示其发展轨迹及走向,分析其成功与不足;2.4节讨论实现动态二进制翻译所必需的体系结构支持;最后,在2.5节,我们将对本章进行简要的小结。 2.1 二进制翻译技术概览 二进制翻译是一个复杂的过程,涉及到许多技术的结合,包括编译技术、计算机体系结构技术、自适应软件技术等等。二进制翻译可以在运行时动态完成也可以在编译时静态实现,可以仅翻译用户级代码也可以翻译整个系统代码。动态二进制翻译是在程序运行期间把代码片段从旧指令集翻译到目标指令集,静态二进制翻译则是在脱机状态下进行翻译工作,然后在运行时执行翻译过的代码。 一个完整的指令集包括许多部分,如寄存器组织、存储器结构、指令、以及自陷和中断方式等等。二进制翻译必须完整地再现这些接口与功能。从根本上讲,二进制翻译是一种软件方法,它的实现可以有三种不同方式:解释执行、静态翻译、动态翻译,这三种方式在效率、实现复杂度、可移植性方面也呈现出不同的特点。表2-1列出了这三种实现方式的优缺点[Cifuentes,1996; Altman,2000]。 表2-1 三种二进制翻译方法的比较 优 点 缺 点 解释执行 易开发,不需用户干涉,高度兼容 代码执行效率很差 离线翻译,可以进行更好的优化,依赖解释器、运行环境的支持,需要静态翻译 代码执行效率较高 终端用户的参与,给用户造成不便 无需解释器和运行环境支持,无需翻译的代码执行效率不如静态翻译动态翻译 用户参与,利用动态信息进行优化 高,对目标机器有额外的空间开销 2.1.1 解释执行 解释器的出现可以追溯到上世纪五、六十年代,许多程序设计语言都采用解释方式执行,如LISP、Perl、FORTH等,但本节仅关心如何采用解释技术实现二进制代码的翻译,而不考虑高级语言的解释。解释器的开发相对容易,也比较容易实现与已有体系结构的高度兼容,但代码执行效率很差。在IBM/360上仿真IBM 1401、7070和7090以及在VAX上仿真PDP-11均采用解释的方法实现。 源处理器源处理器 存储状态上下文块 程序计数器 条件码代码寄存器1 寄存器2 … … 数据寄存器n-1 ... 堆栈解释代码 图2-1 解释器的逻辑结构 图2-1是解释器的基本结构[Smith, 2005],它实时解释并执行源处理器代码中的每条指令,系统不保存也不缓存解释过的指令,整个解释过程无需用户干涉,也不进行任何代码优化。除指令外,源处理器的代码映像还包含一定的数据,为了完整地再现源处理器代码的执行情况,解释器还必须忠实地记录源处理器的运行状态,如程序计数器、寄存器的值。图2-1中的源处理器上下文块(Source Context Block)就是保存处理器状态的存储区。 解释器可以按照“取指令?分析指令?完成指令所需的操作并修改处理器状态”这样的流程解释执行源处理器代码的每一条指令,直至结束。这种解释方式被称为“译码并转发(decode-and-dispatch)”。下面给出了此类解释器的一段示例代码[Smith, 2005],源处理器为PowerPC。在这段代码中,while循环描述了每条指令的解释、分析和执行过程,而每条指令的执行由case语句中相应的函数实现,例如函数LoadWordAndZero()将一个32位存储单元的内容加载到64位寄存器的低32位,并将该寄存器的高32位清零,而函数ALU()则实现了所有的ALU操作。源处理器的程序计数器保存在PC中,而通用寄存器则保存在数组regs[]中。 /* 代码:Decode-and-dispatch解释器基本结构示例代码 */ while (!halt && !interrupt) { inst = code[PC]; // 取指 opcode = extract(inst, 31, 6); // 分析指令 switch (opcode) { // 执行并修改处理器状态 case LoadWordAndZero: LoadWordAndZero(inst); case ALU: ALU(inst); case Branch: Branch(inst); … } } LoadWordAndZero(inst) { RT = extract(inst, 25, 5); RA = extract(inst, 20, 5); displacement = extract(inst, 15, 16); if (RA==0) source = 0; else source = regs[RA]; address = source + displacement; regs[RT] = (data[address]<<32) >> 32; PC = PC + 4; } ALU(inst) { RT = extract(inst, 25, 5); RA = extract(inst, 20, 5); RB = extract(inst, 15, 5); source1 = regs[RA]; source2 = regs[RB]; extended_opcode = extract(inst, 10, 10); switch(extended_opcode) { case Add: Add(inst); case AddCarrying: AddCarring(inst); case AddExtended: AddExtended(inst); … } PC = PC + 4; } Decode-and-dispatch结构解释器的实现非常容易,而且代码可读性好,但由于含有大量分支指令,它的执行效率很低,而且这些分支指令的行为很难预测,很难通过现有的硬件技术提高性能。为了解决这一问题,人们又提出线程解释(threaded interpretation)方法[Klint,1981]。这种方法的核心思想是将译码并转发结构中的转发代码分布到不同类型指令的解释函数中,从而消除一部分分支指令,如下面的代码所示[Smith, 2005]。这时在每条指令的解释代码中只有一条间接分支语句“goto *rountine”了,这条语句的作用是跳转到下一条指令的解释代码入口处。 /* 代码:线程解释器解释函数的代码示例 */ LoadWordAndZero: RT = extract(inst, 25, 5); RA = extract(inst, 20, 5); displacement = extract(inst, 15, 16); if (RA==0) source = 0; else source = regs[RA]; address = source + displacement; regs[RT] = (data[address]<<32) >> 32; PC = PC + 4; if (halt || interrupt) goto exit; inst = code[PC]; opcode = extract(inst, 31, 6) ; extended_opcode = extract(inst, 10, 10); routine = dispatch[opcode, extended_opcode]; goto *rountine; add: RT = extract(inst, 25, 5); RA = extract(inst, 20, 5); RB = extract(inst, 15, 5); source1 = regs[RA]; source2 = regs[RB]; sum = source1 + source2; reg[RT] = sum; PC = PC + 4; if (halt || interrupt) goto exit; inst = code[PC]; opcode = extract(inst, 31, 6) ; extended_opcode = extract(inst, 10, 10); routine = dispatch[opcode, extended_opcode]; goto *rountine; 图2-2比较了这两种解释机制的异同[Smith, 2005]。左边是第一种方法的执行流程,显然这是一种集中的处理方式,右边是第二种方法的执行流程,这是一种典型的分布处理方式,每种指令的解释代码负责下一条指令的取和译码,并根据下一条指令的类型将控制转移到对应的解释代码段。 解释解释 代码代码源处理源处理 器代码器代码 Dispatch 循环 图2-2 两种解释机制的比较 尽管第二种方法能够在一定程度上提高解释执行的效率,但对dispatch数组的访问成为限制性能进一步提高的瓶颈,因为每一段解释代码都必须访问该数组获得下一条指令对应解释代码的入口并通过goto语句跳转到该入口。为了进一步提高效率,人们又提出了减少该数组访问次数的方法,即预译码(Predecoding)技术。采用这种方法,源处理器代码将被转换为某种格式更加规整的中间代码,中间代码的某个字段就保存了该指令对应翻译代码的入口,因而减少了对dispatch数组的方法。中间代码将被缓存起来,再次执行这段源处理器代码时将不再解释,这可以进一步提高效率。这种技术也叫做直接线程解释(Direct Threaded Interpretation),它已经包含了一定的翻译思想。 2.1.2 静态二进制翻译 静态二进制翻译是在二进制代码执行之前对其进行翻译,将源机器上的二进制可执行文件完全翻译成目标机器上的二进制可执行文件,然后在目标机上执行翻译得到的可执行程序,而且一次翻译的结果可以多次使用。静态翻译方法与高级语言的编译过程十分接近。 静态二进制翻译器离线翻译程序,有足够的时间进行更完整、更细致的优化,因而代码执行效率较高,DEC公司的FX!32系统就采用了这种方法。但是,由于缺乏必要的运行时信息,静态翻译程序无法解决代码挖掘和自修改代码这两个二进制翻译过程中的关键问题(这两个问题的定义和解决方法将在2.2节详细介绍),这导致它可能无法完整地翻译一个程序,那些无法翻译的部分只能依赖解释器的解释执行。此外,静态翻译程序往往还需要终端用户的参与,这给用户使用造成了很大不便。 解释执行与翻译执行在一定程度上很相似,因为它们都引入了预译码技术,但它们仍是两种完全不同的技术,图2-3描述了二者的异同[Smith, 2005]。尽管采用这两种方法,源处理器代码都将被转换为另一种形式的二进制目标代码,但解释执行时目标代码还必须依赖对应的解释程序才能间接地在目标处理器上执行,而翻译得到的目标代码可以直接在目标处理器上执行。 解释 代码中间目标处理 代码器代码源处理源处理 器代码器代码 二进制预翻译翻译程程序序 图2-3 解释方法与翻译方法的异同 由于所得到的目标代码执行效率较高,静态翻译技术能够被很好地应用在面向特定应用的指令扩展中。指令扩展技术向指令集中增加某些新指令以提高处理器面向特定应用的性能,其核心思想是找出应用程序数据流图(Data Flow Graph,DFG)中对性能影响较大的关键子图,这些子图往往具有很高的执行频率,每个子图被压缩为一条指令在专门定制的硬件功能单元上执行。目前指令扩展技术在嵌入式处理器,特别是专用指令集处理器(Application Specific Instruction-set Processor,ASIP)[Keutzer, 2000]的设计中得到了广泛应用。除了以获得最大性能加速比为目标外,有时指令扩展还必须综合考虑面积、功耗等其它约束。 指令扩展包括子图识别与压缩两个阶段,前者负责识别出源二进制代码中所有的关键子图,而后者将每个被识别出的子图转换为目标指令集中的扩展指令并重新进行优化调度,得到目标二进制代码。这两个阶段的工作既可由软件静态实现,也可以通过硬件动态完成,考虑到二者之间的顺序关系,一共存在三种可能的实现方式。 一是静态识别静态压缩,这也是最传统的指令扩展方法,其流程如图2-4所示,在传统的编译流程中增加了子图识别和子图压缩两个阶段(图中灰色部分),可以采用时间较长的优化算法,但对于每个目标指令集都必须重复这一过程。实际上,静态二进制翻译也采用图2-4所示的流程,只不过静态二进制翻译时需要识别和压缩的子图数量远远多于指令扩展时要处理的,如果我们将扩展指令集合扩展为目标机的指令集,那么图2-4描述的就是一个完整的静态二进制翻译过程。第二种方法则是动态识别动态压缩,以Clark等人提出的基于rePlay的动态指令扩展[Clark,2004]最具代表性。rePlay是一种能够记录处理器执行过的指令序列的硬件机制,根据它记录的信息可以识别出程序中频繁执行的指令序列并动态地将其转换为扩展指令。这种方法的优点在于保证了源指令集与目标指令集的兼容,但它的硬件复杂度过高而且无法采用时间复杂度较大的优化算法。一般只能采用贪婪算法识别关键子图以保证实时性,但可能会影响最终的性能加速比。为降低硬件复杂度,Clark等人中又提出了一种静态识别动态压缩方法[Clark,2005],即第三种方法,静态翻译时识别出可以作为扩展指令执行的子图并用专门的指令标识出来,而在运行时则利用硬件机制将其动态转换为扩展指令。这种方法兼具了前两种方法的优点,既通过静态子图识别算法提高了性能加速比,又通过rePlay硬件机制保持了源、目标指令集之间的兼容。 指令寄存器指令子图子图DFG调度分配调度识别压缩456123 图2-4 静态指令扩展流程 采用静态翻译方法还可以很容易地实现两个不同的扩展指令集之间的兼容,例如两个不同的SIMD(Single Instruction Multiple Data)指令集之间的兼容。SIMD指令能够充分利用32、64乃至128位的数据带宽,同时处理多个宽度比较小的数据,从而提高多媒体等应用的性能,Intel的MMX/SSE和AMD的3D Now!指令集都是在x86指令集上扩展出的SIMD指令集,此外PowerPC等其它处理器也定义了自己的SIMD扩展指令集。为了实现这些格式各异的SIMD指令集件的兼容,Clark提出了一种静态识别和动态压缩相结合的SIMD指令虚拟化方法[Clark,2007]。它首先将不同的SIMD指令集转换为某种中间格式,然后借助rePlay硬件在运行时将中间代码动态转换为目标指令集中的SIMD指令。这一方案也可以很容易地推广到实现其它扩展指令集之间的兼容。 2.1.3 动态二进制翻译 动态二进制翻译则在程序运行时对执行到的片断进行翻译,丰富的运行时信息使它克服了静态翻译的一些缺点,例如由于无法知道控制流中某点的寄存器或存储单元的值,静态二进制翻译无法解决代码挖掘问题。动态二进制翻译还可以解决大部分实际情况中的自修改代码问题,这是静态二进制翻译不可能做到的。2.2.2节将详细介绍动态翻译系统中如何解决这两个问题。动态翻译还可以利用运行时的动态信息来发现静态编译器所不能发现的优化机会。此外,动态翻译器对用户可以做到完全透明,无需用户干预。比较有代表性的动态翻译系统包括JVM,BOA,Aries等,我们将在2.3节详细介绍这些系统的结构并分析其特点。 图2-5给出了一个简单的动态翻译系统结构框图[Smith, 2005],它由四个部分组成:Manager负责整个系统的控制;代码Cache 保存翻译得到的目标代码;地址映射表记录源机器程序指令地址(Source PC,SPC)与目标机器程序指令地址(Target PC,TPC)的对应关系,若源程序中起始地址为SPC的代码段已经被翻译并保存在代码Cache中(假设目标代码起始地址为TPC),映射11表中将有一项;翻译模块(Translator)负责完成从源指令集到目标指令集的翻译。 11 源代码 ManagerMiss Translator TPCSPC11 ......HitTPCSPC00 目标代码 地址映射表 图2-5 一个简单动态翻译系统的结构框图 动态翻译和执行过程如下:首先,Manager查找源机器程序的入口地址SPC在映射表中是否有对应项;若命中(Hit)则直0 接从代码Cache中取出相应的一个目标代码块执行,直至该块的出口,若出口地址为SPC,则继续查找映射表中有无SPC对应tt的项;若不命中(Miss),则Manager将启动翻译模块,从SPC开始取源机器程序的一个基本块进行翻译,翻译结果将被存入0 代码Cache,并在地址映射表中添加相应项(设目标代码块地址为TPC);这一过程将一直重复,直到程序执行结000 束。 可以看出,源机器代码的翻译和目标代码的执行均以基本块为单位进行。需要注意的是,此处所指的基本块为“动态基本块”,不同于编译过程中处理的“静态基本块”。图2-6指明了二者的区别:静态基本块(左)的入口为程序的第一条指令或控制类指令的目标指令,出口为控制类指令或其他某基本块入口之前的一条指令;动态基本块(右)则根据运行时控制流的实际情况决定,通常比静态基本块大[Smith, 2005]。动态翻译的过程决定了它所识别出的基本块都是动态基本块。 另外,代码Cache的管理也需要通过Manager中的专门模块完成。代码Cache是主存中一块专门用于保存翻译后目标代码的空间,容量有限,为了提高这块存储空间的利用率,需要采用特定的替换策略对其进行管理,使得其中尽可能地存放近期将被使用的目标代码。人们已经提出了多种代码Cache替换策略,包括:最近最少使用算法(Least Recently Used,LRU),每次换出最近最少被访问的目标代码块;清空算法(Flush when full)[Cmelik,1994],每当代码Cache没有足够的空间容纳新的目标代码时将整个Cache清空;Preemptive Flush算法,监测动态翻译执行过程中翻译模块的工作频率,若在某段时间内翻译模块工作频率较高,则意味着当前执行的目标代码极可能首次被翻译执行,并清空代码Cache,这种方法充分利用了程序执行的时间局部性原理;细粒度FIFO(First-In-First-Out)算法,每次换出最先进入代码Cache的目标块;粗粒度FIFO算法,将整个代码Cache分为若干子块,按照FIFO方式清空其中最先被使用的子块。Hazelwood等分析了上述替换算法的性能,发现8个子块的粗粒度FIFO替换算法的开销最小[Hazelwood,2004]。 add ... load ... add ... store ... load ...Block 1loop: load ... store ... add ...loop: load ... store add ...Block 1 brcond skip storeBlock 2 load ... brcond skip sub ... load ...Block 3skip: add ... sub ... storeskip: add ...Block 2 brcond loop storeBlock 4loop: load ... brcond loop add ... add ... store load ...Block 3Block 5 brcond skip store ... skip: add ... jump indirect store ...Block 4 brcond loop ... ... ... 图2-6 静态基本块与动态基本块 除了根据SPC查找对应的TPC外,代码Cache管理模块还必须提供根据TPC反向查找SPC的功能,这是实现精确异常处理所必需的,有关异常处理将在2.2.1节讨论。为此,可以设置一个与地址映射表相似的表格(Side Table)记录TPC与SPC之间的对应关系。 2.1.4 二进制翻译系统框架 由于上述三种翻译方法各有所长,真正实现一个二进制翻译系统时一般会结合使用上述三种方法中的两种或全部。下面以 解释执行和动态翻译相结合的二进制翻译系统框架为例简略描述一个二进制翻译系统的翻译执行过程,如图2-7所示。实际上许多真实系统都采用类似的框架实现[Ebcioglu,1997; Zheng,2000; Gschwind,2000c; Cifuentes,2002]。 源机器 代码片段 源机器 解释器代码 解码 翻译翻译系统启动模块动态 优化控制模块(加载程序)翻译器 编码 运行环境 本地码执 行模块仿真模块调用关系 目标机器 代码片段数据流 目标机器平台 图2-7 二进制翻译系统框架 一个解释执行和动态翻译相结合的二进制翻译系统,通常包括控制模块、启动模块、运行环境仿真模块、解释器、动态翻译器、本地码执行模块等主要模块。控制模块控制整个系统的翻译执行过程,从而可以使系统的工作对用户透明;本地码执行模块负责在翻译系统自身的执行和生成的目标机器代码执行之间的切换;运行环境仿真模块支持源机器代码调用、系统调用以及处理信号。 整个翻译执行过程如下:在目标机器平台下执行源机器代码时,嵌入操作系统的启动模块启动整个翻译系统,并将源机器代码加载到内存中,然后控制模块启动解释器对源机器代码解释执行,并根据需要记录代码执行路径、执行次数等程序运行信息。若某段源机器代码的执行次数超过某个阈值,就启动动态翻译器对其进行翻译、简单优化、编码生成目标机器代码片断并缓存在专门的缓存区内。目标机器代码片段缓存区的维护工作也由翻译系统控制模块完成。这些被翻译执行的代码片段被称为“热点代码(Hotspot)”,它们的执行频率或次数被称为“热度”。此后,再次执行到该源机器代码片断时就不再解释执行,而是通过本地码执行模块来直接执行翻译生成的目标机器代码。 为了提高翻译后的代码效率,对于那些执行热度极高的目标机器代码片断,还需要对其进一步优化,这就会用到2.1.5节介绍的动态优化技术。另外,由于解释执行的开销很大,IA-32 EL等系统采用了直接翻译的方式。 2.1.5 动态优化 在从源代码编译生成机器指令的过程中进行优化对于提高应用程序的运行速度具有重要作用。研究者已经提出了众多的变换和优化算法,以提高编译器生成代码的效率。然而,这种传统的静态编译优化方式存在着多种限制。 静态编译优化的一个主要不足是编译时无法准确预测程序的动态行为。通过收集程序在样例输入下的运行时信息来指导优化过程只能部分地改善问题,因为这样的运行时信息只是程序代码行为的平均反映,不能指示统一代码段在运行中的阶段性行为,而且样例运行也无法代表最终用户的运行模式。在软件技术的近期发展中,面向对象程序设计语言的广泛使用以及以动态链接库形式发布软件的倾向,导致程序中出现越来越多的运行期绑定,这进一步增加了传统静态编译优化的难度。 解决这一问题的一种方法就是使用运行时的动态优化技术。与传统的编译器优化不同,运行时动态优化将在程序的执行过程中持续检测程序运行的统计信息,并根据这些信息对程序代码进行变换,以得到程序代码的优化版本并运行。运行时动态优化直接操作在程序的二进制代码上,不需要程序设计语言或编译器的注释,这不仅使得优化对用户完全透明,还给遗留代码的执行提供了额外的性能提升机会。 动态优化技术与二进制翻译技术具有密切的关系,它既可以作为一种独立的代码优化技术,又可以作为二进制翻译所必需的后端优化器,一般的动态二进制翻译系统都会结合动态优化技术来改善系统性能,同时二进制代码的动态优化过程也需要解释器等模块的支持。有时,我们也可以将动态二进制翻译系统视作动态优化系统的一个特例,其中源指令的解释执行为未经优化的执行,而代码翻译就是一种优化变换。 动态优化技术的核心思想是在应用程序运行时对程序的动态执行信息进行收集和分析,并对程序的关键段进行必要的优化,从而提高程序的性能。例如系统可以在运行时将执行频率较高的连续若干基本块组合在一起,得到一个体积更大、包含更多指令的基本块,重新调度其中的指令往往能够开发出更多的指令级并行。由于在程序运行过程中可以获得静态分析时所无法获取的程序行为和环境信息,如运行时常量、用户偏好和访问模式、程序执行阶段变化、以及特殊处理器结构与内存系统等,因此与静态编译器优化相比,动态优化能够更好地适应程序的行为。但在运行时对程序进行上述处理要耗费相当多的时间,这部分开销被计入程序的执行时间,所以动态优化必须及时发现程序的关键段,并采用快速而高效的分析、优化手段,以获得理想的优化效果。动态优化系统所用到的热路径选择技术可以用纯软件方式实现,若能得到硬件结构的有效支持,动态优化系统的效率还可以获得显著提高。 高效的二进制翻译机制必须同时兼顾正确性和高效率,为了在不同系列的CPU间实现软件平滑移植,动态翻译往往只能够保证程序执行的正确性,而翻译过程会产生较大的开销。为了补偿这些开销,只能通过动态优化手段提高目标机代码的质量,这种需求极大地推动了动态优化的研究。即便对于同一个系列的处理器产品,由于不同“代”产品之间实际硬件资源的差异,面向旧芯片的可执行代码虽然可以直接在新的芯片上执行,但由于不能充分利用新的功能部件,程序的效率也会受影响,这也 需要动态优化技术对其加以改进。 第三章 计算系统虚拟化方法 本章详细介绍系统级虚拟化技术。首先介绍资源(CPU、内存和I/O设备)虚拟化方法的研究现状和发展趋势,包括全虚拟化、半虚拟化、预虚拟化技术等纯软件方法,以及硬件辅助虚拟化技术;其次介绍为了适应虚拟机环境,客户操作系统的适配技术,包括为迁入虚拟化环境、为支持虚拟机管理、为特殊项目定制等目的而进行的客户操作系统适配;然后介绍系统级虚拟化技术在多机环境下的扩展,最后比较系统级虚拟化与进程级虚拟化和语言级虚拟化的异同,并简要介绍了系统级虚拟化和网格计算技术的融合。 3.2 系统级虚拟化概述 系统级虚拟化技术源于上世纪60年代,其核心思想是:在一台物理主机上虚拟出多个虚拟计算机(Virtual Machine,VM),每个虚拟计算机可以看作一个物理主机的副本,各虚拟计算机相互隔离,其上能同时运行独立的操作系统,这些客户操作系统(Guest OS)通过虚拟机管理器(Virtual Machine Monitor,VMM)访问实际的物理资源(如图3-1所示)。 应用程序应用程序应用程序 客户操作系统客户操作系统客户操作系统„„(Guest OS)(Guest OS)(Guest OS) 虚拟硬件虚拟硬件虚拟硬件 虚拟机监控器(VMM) 硬件(CPU、内存、硬盘等) 图3-1 虚拟机的基本结构 系统级虚拟化技术其本质是多个虚拟机复用一组物理资源,由虚拟机管理器实现对底层资源的划分和共享,向上表现出多组虚拟计算资源。划分指虚拟机管理器将实际的物理资源分成若干部分,每个虚拟机及虚拟机管理器能访问其中的一个或几个部分,虚拟机管理器通常需要将这些部分伪装成实际的完整的物理设备,并保证虚拟机资源之间的隔离性。共享是指多个虚拟机使用同一个完整的物理设备,通常采用分时复用的机制,虚拟机管理器实现物理资源在不同虚拟机和虚拟机管理器之间轮转。如果设备有内部状态,则需要在虚拟机切换时,由虚拟机管理器保存前一个虚拟机的设备状态,并载入下一个虚拟机的状态。现有的虚拟机系统,一般用划分的方式虚拟化内存和一些可划分的I/O设备,例如磁盘设备;用共享的方式虚拟化CPU及其它支持共享的设备或不可划分的设备。 系统级虚拟化需要满足一致性、高效性和可控性[G.Popek & R.Goldberg,1974]:一致性是指程序在虚拟机上运行的效果必须与物理主机上运行的效果一致,仅存在时间和可用资源的不同带来的区别;高效性是指程序在虚拟机上运行造成的性能代价较低,即必须保证虚拟机的大部分指令都可以直接在物理主机上运行;可控性是指VMM能够完全控制物理主机的资源,一方面要保证一个虚拟机不能访问另一个虚拟机的资源,另一方面要保证VMM能够收回已分配给虚拟机的资源。现有的一些虚拟化技术都满足这三方面的需求,仅在虚拟化性能上有差异。 传统的虚拟化技术,主要使用“特权解除”(Privilege deprivileging)和“陷入-模拟”(Trap-and-emulation)的方式[G.Popek & R.Goldberg,1974],将客户操作系统运行在非特权级,则当客户操作系统中执行到状态和控制相关指令时,能够陷入虚拟机管理器,由虚拟机管理器对指令进行监控和模拟。其代表系统是IBM VM/370。 近年来,随着单机计算能力的不断提高,虚拟机技术重新受到重视并得到快速发展。学术界和工业界展开了虚拟化x86硬件的大量研究,出现了资源虚拟化的新技术,包括以VMware为代表的二进制代码动态翻译技术(Dynamic binary translation),以Xen为代表的半虚拟化技术(Para-virtualization),以及德国Karlsruhe大学、澳大利亚新南威尔士大学和IBM的研究人员共同提出的预虚拟化技术(Previrtualization)[J.LeVasseur et al.,2005]。x86硬件的两大生产商Intel和AMD则对x86体系结构进行了扩展,实现了硬件虚拟化支持[AMD,2005;Intel,2006]。同时,在网络环境下利用虚拟机易管理维护易备份迁移的特性,出现了大量利用虚拟机环境进行安全性、可信性、易管理性等方面的应用研究。 Guest AppsGuest Apps Guest AppsGuest OSGuest OS User ModesGuest OSVMMVMM VMMHost OSHost OSSystem Modes HardwareHardwareHardware A.B.C. Stand aloneUser-mode hostedDual-mode hosted 图3-2 Stand alone VMM与Hosted VMM (图片来自[J.Smith & R.Nair,2006]) 从系统构架来看,虚拟机管理器(VMM)是整个虚拟机系统的核心,它承担了资源的调度、分配和管理,保证多个虚拟机能够相互隔离的同时运行多个客户操作系统(Guest OS)。虚拟机管理器运行在硬件平台之上,客户操作系统之下,不同的系统需求有不同的实现方式,常见的虚拟机管理器在系统中的层次如图3-2所示[J.Smith & R.Nair,2006]。 图3-2A中,VMM运行在硬件平台上,使用硬件接口,完成资源虚拟化和虚拟机管理,Guest OS运行在VMM之上,使用VMM提供的指令集和设备接口,这种结构也称为Type I VMM。该结构通常能获得较好的性能,但是由于VMM需要直接和硬件交互管理所有设备,实现较为复杂,代表系统有Xen和VMware ESX Server。图3-2B中,VMM运行在操作系统之上,该操作系统通常称为宿主操作系统(Host OS),这种结构也称为Type II VMM,VMM在用户模式实现,可以利用宿主操作系统的资源管理、调度等功能,因而资源虚拟化和虚拟机管理实现较为容易,但虚拟化性能通常较低,代表系统有VMware Workstation。图3-2C与3-2B类似,但一部分VMM功能实现在系统模式,能够直接访问硬件,从而能够同时获得较高的性能和较简易的实现,其代表系统有KVM[Qumranet,2006]。 本章主要介绍系统虚拟化技术,首先介绍资源虚拟化方法,包括对处理器、内存和I/O设备的虚拟化方法,其次介绍在虚拟机环境下客户操作系统的适配技术,以及系统级虚拟化技术在多机环境下的扩展,最后简要介绍进程级和语言级虚拟化技术。 3.3 CPU虚拟化 CPU的虚拟化是为每个虚拟机提供一个或多个虚拟CPU(Virtual CPU,VCPU)。多个虚拟CPU分时复用物理CPU,任意时刻一个物理CPU只能被一个虚拟CPU使用。VMM必须为各虚拟CPU合理分配时间片并维护所有虚拟CPU的状态,当一个虚拟CPU的时间片用完需要切换时,要保存当前虚拟CPU的状态,将被调度的虚拟CPU的状态载入物理CPU。因此CPU虚拟化需要解决以下两个问题:1)虚拟CPU的正确运行;2)虚拟CPU的调度。 虚拟CPU正确运行的关键是保证虚拟机的指令正确执行,各虚拟机之间不互相影响,即指令的执行结果不改变其他虚拟机的状态。现有的实现技术包括模拟执行和监控执行[J.Smith & R.Nair,2006]。模拟执行是指由VMM模拟所有指令的运行效果,包括解释执行和二进制代码翻译。通常用在物理机器指令集与虚拟机指令集不同的情况下,模拟执行方式效率较低。监控执行是指虚拟机的绝大部分指令都能在物理主机上直接执行,少量可能影响虚拟机运行或影响其他虚拟机状态的指令(称为“敏感指令”),必须由VMM监控并模拟其执行效果,在某些系统中,被VMM监控的指令的可能需要采用解释执行或二进制代码翻译的方式模拟执行。监控执行方式效率较高,在理想状态下,虚拟机甚至可以达到接近物理主机的速度。实际情况下,虚拟机的效率很大程度取决于需要被VMM监控执行的指令运行的性能,包括需要VMM模拟运行的指令的数量,发现需要监控的指令的复杂度,用于指令模拟的数据结构和算法的性能。本节主要讨论监控执行。 虚拟CPU的调度是指由VMM决定当前哪一个虚拟CPU实际在物理CPU上运行。虚拟CPU的调度除了保证虚拟机之间的性能隔离性,还应该保证虚拟CPU的性能,保证调度的公平性:要考虑调度算法既能够充分利用物理CPU资源,又能实现精确的CPU资源分配;要根据虚拟机上运行的应用服务的特点以及虚拟机之间的依赖关系合理调度虚拟CPU。 本节首先介绍一个经典的虚拟化模型,并给出采用经典的虚拟化方法对指令集体系结构(Instruction Set Architecture,ISA)的要求;然后主要讨论x86体系结构的虚拟化方法,包括x86体系结构对虚拟化的支持,x86硬件平台上现有的虚拟化方法——软件解决方案和硬件辅助虚拟化技术,并讨论多核的趋势下CPU虚拟化的新问题;最后讨论虚拟CPU的调度。 3.3.1 经典虚拟化的逻辑模型 经典的监控执行方式的虚拟化通常采用“特权解除”(Privilege deprivileging)和“陷入-模拟”(Trap-and-emulation)的技术。“特权解除”是指为了实现VMM对虚拟机的控制,降低客户操作系统运行的特权级别,而将VMM运行在最高特权级。解除了客户操作系统的特权之后,客户操作系统的大部分指令仍可以在硬件上直接运行,只有当客户操作系统执行到特权指令时,才会陷入到最高特权级的VMM模拟执行,即实现“陷入-模拟”。 采用“特权解除”和“陷入-模拟”技术实现的VMM可以划分为三种逻辑模块:调度器(Dispatcher)、分配器(Allocator)和一组解释器(Interpreter),每一个解释器模拟一条特权指令的执行效果,它们之间的关系如图3-3所示[J.Smith & R.Nair,2006]。 陷入 访问特权资源 的指令调度器解释器 1 解释器 2可能改变系统资 源分配的指令 … 分配器解释器 n 图3-3 “陷入-模拟”的逻辑模型 (图片来自[J.Smith & R.Nair,2006]) 当虚拟机执行到某一条特权指令而陷入到VMM后,首先由调度器对该指令进行分析,若该指令是对系统资源进行调整,则交给分配器进行资源调整;否则,分配给相应的解释器模拟其操作,模拟执行完成后,返回虚拟机执行该特权指令的下一条 指令。以上步骤完成了一次“陷入-模拟”。 3.2.1.1. 虚拟化对ISA提出的要求 “特权解除”和“陷入-模拟”对物理主机的ISA有一定的要求: 首先,由于“特权解除”要降低客户操作系统所在的特权级,因此, [条件1] CPU必须支持多个特权级。 此外,必须保证由VM直接运行的指令必须能在较低的特权级上正确执行,也就是说客户操作系统中的非特权指令在较低的特权级上执行必须与在最高特权级上执行具有相同的效果。因此, [条件2A] 如果非特权指令的执行效果不依赖于CPU的特权级,则该指令集支持“特权解除”的虚拟化方式。[J.S.Robin & C.E.Irvine,2000] “陷入-模拟”的本质是保证可能影响VMM或VM正确运行的指令由VMM监控执行。在早期的虚拟机研究中,Popek和Goldberg[G.Popek & R.Goldberg,1974]提出了“陷入-模拟”的实现对ISA的形式化需求: [条件2B] 如果敏感指令都是特权指令,则此指令集体系结构的计算机支持虚拟化。 其中,敏感指令包括可能改变CPU状态(如特权级)的指令,或其执行结果依赖于CPU特权级的指令(因此,条件2B包含了条件2A)。当采用“特权解除”的方式,客户操作系统运行在非最高特权级时,客户操作系统执行任意特权指令都会发生陷入。因此该条件保证了任何影响VMM或VM正确运行的指令在VM上执行时都能被VMM捕获并将控制权转移到VMM,从而保证了虚拟机环境的等价性和资源可控性,保证虚拟机能正确运行。 为保证虚拟机之间的隔离性,还需要, [条件3] ISA必须支持一种保护机制,例如段保护或页保护,从而保证多个虚拟机之间的隔离。[J.S.Robin & C.E.Irvine,2000] 若一个ISA满足上述四个条件,则可以说这个ISA支持“陷入-模拟”虚拟化。 3.2.1.2. x86 ISA分析 x86体系结构符合条件1——x86支持4个特权级ring0,ring3(Intel64除外),一种特权解除的实现方式是将VMM运行在0特权级,客户操作系统降低到1特权级,其上的应用程序仍然运行在3特权级。同时,x86也符合条件3:x86支持分段或分页的保护机制。 但是x86体系结构不符合条件2[J.S.Robin & C.E.Irvine,2000]——其指令集中有一部分敏感指令不是特权指令,在低特权级下运行不会发生陷入,无法由硬件保证VMM能接管所有状态和控制相关指令。这部分指令包括两类,其一,一部分指令其运行结果受到当前特权级的影响,例如POPF在0特权级与在非0特权级的执行效果不同;其二,一部分访问敏感资源的指令不是特权指令,例如PUSH指令能够访问敏感寄存器,但不是特权指令,当客户操作系统执行PUSH CS后可能发现自己没有运行在最高特权级。因此x86 ISA不支持简单的“特权解除”和“陷入-模拟”的虚拟化实现。 3.3.2 x86的CPU虚拟化方法 由于x86 ISA并不支持“陷入-模拟”的虚拟化,所以长期以来对x86平台的虚拟化都是通过软件方式实现,以保证需要监控的指令能够发生陷入,最具代表性的是二进制代码动态翻译(Dynamic binary translation)、半虚拟化(Para-virtualization)和预虚拟化技术(Previrtualization)。近期,x86的两大生产商Intel和AMD分别扩展了x86 ISA,使x86硬件也支持“陷入-模拟”方式的虚拟化,下文分别介绍软件实现方式和硬件扩展技术。 3.3.2.6 二进制代码动态翻译技术 二进制代码动态翻译在执行时动态地重写虚拟机的执行代码,在需要虚拟机管理器监控和模拟的位置,即敏感指令前,插入陷入指令。该技术的优势在于客户操作系统能够不经修改直接在虚拟机上运行,其缺点是动态翻译带来一定的性能开销。VMWare公司的虚拟机产品VMWare WorkStation和VMWare ESX Server采用该技术实现CPU的虚拟化,并通过翻译结果缓存、翻译结果优化等技术减小动态翻译带来的性能损失。微软公司的Virtual PC也采用二进制翻译技术,并支持多种指令集之间的翻译。 以VMware的二进制代码动态翻译[K.Adams & O.Agesen,2006]为例,其输入是链接后的二进制代码,是完整x86指令集;翻译后输出也是二进制代码,但只是x86指令集的一个子集,其中的一些敏感指令被替换成陷入指令。翻译过程与指令运行交叉进行,翻译器逐条读取二进制指令,每条指令生成中间表示(Intermediate Representation,IR);若干条IR组成一个翻译单元(Translation Unit,TU),每个TU以跳转指令结束,最多有12条指令;除跳转指令外,所有指令都能被确定地翻译。TU经过翻译后,生成已编译的代码片断(Compiled Code Fragment,CCF),CCF是可以直接运行的二进制代码片断。 为了提高动态翻译的性能,VMware采用了一些优化[K.Adams & O.Agesen,2006]: 一是提高翻译速度。在翻译过程中,把TU,CCF的对应关系记录在一个Hash表中,CCF放入翻译缓存(Translation Cache,TC)。一个CCF执行结束后,若下一个要执行的TU对应的CCF缓存在TC中,则直接转移到目标CCF运行,避免了重复翻译。记录TU,CCF对应关系的Hash表是用于提高查找速度。一般地,运行一段时间后,程序所需的大部分CCF都已经保存在TC中,并建立好了连接关系。 二是减少需要翻译的代码量。VMware允许虚拟机上的用户代码直接运行,只需要对内核代码使用二进制翻译。此外,还实现了按需翻译,即只翻译将要执行的指令。 三是降低陷入次数。在不影响系统正常运行的前提下,1)只维护虚拟结构,避免特权指令发生陷入,比如CLI指令,可以 只清空虚拟CPU的标志位IF;2)“innocent until proven guilty”,首先正常翻译,如果CCF执行时发生大量陷入,则重新翻译,使用解释器运行该段指令,从而避免一个CCF中多次发生陷入。 通过优化以后,VMware的CPU虚拟化也表现出较好的性能。 3.3.2.7 半虚拟化技术 半虚拟化技术通过修改客户操作系统的源代码,将待监控的操作替换为对虚拟机管理器的超级调用(Hypercall)。该技术的优势在于虚拟机能够在硬件上直接运行,使客户操作系统能获得接近直接在裸机上运行的性能;其缺点则是需要修改客户操作系统的源代码,使虚拟机上使用的操作系统类型受到限制。美国华盛顿大学2001年设计了Denali系统[A.Whitaker et al.,2002],在Denali系统中提出并实现了半虚拟化技术,用于在同一台机器上部署大量的网络服务系统。英国剑桥大学开发的著名的Xen系统受Denali启发,采用半虚拟化技术实现其CPU的虚拟化[P.Barham et al.,2003]。 以Xen的半虚拟化[P.Barham et al., 2003]为例,Guest OS源码中的一个特权操作被替换成一个Hypercall,类似于操作系统中的系统调用。通过调用Hypercall,Guest OS能够把控制权转移到VMM。例如,一个更新页表的操作,被替换为一个Hypercall,运行时,通过Hypercall陷入到VMM中,由Xen确认并完成,再把控制权返回给产生本次调用的虚拟机。由VMM到虚拟机的通信是由一个异步时间机制提供的,这个机制取代了设备中断方式,虚拟机中可以设置事件屏蔽位,能实现对事件的屏蔽,效果类似于中断屏蔽。 3.3.2.8 预虚拟化技术 预虚拟化技术[J.LeVasseur et al.,2005]通过修改编译器,将操作系统中需要虚拟机管理器监控和模拟的指令在编译时替换为对虚拟机管理器接口的调用。该技术由德国Karlsruhe大学、澳大利亚新南威尔士大学和IBM的研究人员共同提出,并实现了基于微内核系统L4Ka的虚拟机系统,其优势在于无需修改客户操作系统就能获得半虚拟化的性能。 3.3.2.9 硬件辅助虚拟化技术 为了弥补处理器的虚拟化缺陷,x86处理器的两大生产厂商Intel和AMD都推出了各自的硬件虚拟化技术。其基本思想是引入新的指令和处理器运行模式,使得虚拟机管理器和客户操作系统运行在不同的模式下。客户操作系统只能在受控的模式下运行,当需要由虚拟机管理器进行监控和模拟时,由硬件支持模式切换。硬件虚拟化支持使得客户操作系统能够直接运行在物理硬件上,提高了虚拟化性能,也极大的方便了虚拟机管理器的设计和开发。 Intel推出了针对指令集虚拟化的Intel VT-x[Intel,2006]和Intel VT-i[Intel,2005]虚拟化技术(Vanderpool),该技术增加了在虚拟状态下的两种处理器工作模式:Root操作模式和Non-root操作模式。虚拟机管理器运行在Root操作模式下,客户操作系统运行在Non-root操作模式下。开始时通过执行VMXON指令进入虚拟化状态,处理器运行在Root操作模式下,执行虚拟机管理器的代码,当虚拟机管理器要运行一个虚拟机时,执行VMLAUNCH指令使处理器发生VM Entry,进入Non-root操作模式,运行客户操作系统指令。此时,若遇到需要虚拟机监控和处理的指令或事件时,处理器会发生VM Exit,回到Root操作模式,由虚拟机管理器进行处理。处理完成后,通过VMRESUME指令,再次发生VM Entry,进入Non-root操作模式继续运行客户操作系统的指令。VMXOFF指令使处理器退出虚拟化状态。切换过程如图3-4所示。 Guest 0Guest 1 VMM VMXOFFVM ExitVMXONVM Entry Normal IA32/Intel64 Operation VMX Root Operation VMX Non-Root Operation 图3-4 Intel VT的操作模式切换 虚拟机控制结构(VM Control Data Structure,VMCS)[Intel,2006]管理Root和Non-root之间的切换,并控制Non-root模式时的CPU行为。VMCS中保存的数据包括: 1. 虚拟状态数据(Guest-state area),保存虚拟机的CPU状态,当发生VM-exit时,将当前处理器的状态写入该域,当发生VM-entry时,从这个域载入处理器的状态; 2. 主机状态数据(Host-state area),保存主机的CPU状态,当发生VM-exit时,从这个域载入CPU状态; 3. 虚拟机执行控制域(VM-execution control fields),该域控制Non-root模式下CPU的行为; 4. VM-exit控制域(VM-exit control fields),该域控制什么时候发生VM-exit(除了特权指令); 5. VM-entry控制域(VM-entry control fields),控制VM-entry的行为; 6. VM-exit信息域(VM-exit information fields),保存VM-exit时的一些信息,描述了VM-exit的原因。 VMM可以为每一个虚拟CPU维护一个VMCS,软件能够对VMCS的大部分控制域进行配置,以配置Root和Non-root的运行环境,包括Non-root模式下可以引起VM Exit的指令和事件,寄存器的读写控制权限等。 AMD也推出了相似的硬件辅助虚拟化技术AMD SVM(Pacifica)[AMD,2005]。硬件辅助虚拟化技术有助于简化VMM的设计,提高虚拟化性能。目前,VMWare、微软以及Xen都发布了支持硬件辅助虚拟化的版本,并出现了基于硬件辅助虚拟化技术实现CPU虚拟化的虚拟机管理器KVM,Linux的2.6.20版本已经将KVM纳入到内核源码中。但是,以现有的基于硬件辅助虚拟化的实现技术来看,性能优势并未体现出来[K.Adams & O.Agesen,2006],其主要原因在于:1)配置了较严格的虚拟机运行环境,造成了大量的环境切换;2)目前虚拟机的CPU状态,包括大量的寄存器信息都保存在内存中,每次切换都发生大量的内存读写操作。 3.3.2.10 多核CPU的虚拟化 带有硬件虚拟化支持的多核CPU的虚拟化实现,一是要实现多核的划分,二是要实现单核的共享。 多核的划分指将一个或多个核指派给一个虚拟机使用,多个虚拟机可以真正的同时运行。对每一个核,可以利用其硬件虚拟化支持实现虚拟机管理器对虚拟机的监控。 单核的共享指多个虚拟机分时复用同一个核心,其方法和技术与单核CPU的虚拟化相同。 3.3.3 虚拟CPU的调度 虚拟CPU(Virtual CPU,VCPU)的调度是指由VMM决定当前由哪一个虚拟CPU实际在物理CPU上运行。虚拟CPU的调度影响虚拟机的性能,必须保证虚拟机之间的性能隔离,保证调度的公平性。 3.3.3.11 虚拟机环境的调度需求 1. 充分利用CPU资源 为了减小虚拟化的性能开销,使虚拟机尽可能接近物理主机的性能,调度算法需要保证物理CPU资源能充分利用,不浪费任何处理器周期。因此,通常采用work-conserving型调度算法。 2. 支持精确的CPU分配[L.Cherkasova et al.,2007] 在很多应用中,需要精确地为各虚拟机分配CPU资源,因此VCPU的调度算法必须支持对VCPU所用资源的限制。而work-conserving型调度算法一般允许VCPU在没有其它需要运行的VCPU时能长期使用CPU(例如不能指定一个VCPU只能使用50%的CPU资源),因此也需要非work-conserving型的调度算法。 3. 性能隔离 VCPU的调度必须保证一个VCPU的运行不会影响其它VCPU的性能。 4. 考虑虚拟机之间的不对等[L.Cherkasova et al.,2007] 目前虚拟机常见的应用是服务器整合,可以把若干应用服务器合并在一台物理主机上分别作为不同的虚拟机同时运行。这些虚拟机可能有不同的应用特点,例如,交互/批处理,I/O密集/计算密集等,VCPU的调度策略必须考虑这些虚拟机之间的不对等。 5. 考虑虚拟机之间的依赖[L.Cherkasova et al.,2007] 一些虚拟机管理器系统的特点使得虚拟机之间有相互依赖关系,例如Xen中,非特权虚拟机DomU需要依赖特权虚拟机Dom0完成I/O操作,这样的情况下,对Dom0的调度也将会影响DomU的性能。 此外,多CPU主机上,为了保证全系统的负载平衡,可能需要在物理CPU之间迁移VCPU,VCPU的迁移较为复杂。因此一个适宜虚拟机环境的VCPU调度算法可能需要优先考虑更本地化的调度。 以上条件只是列出了在选择虚拟CPU调度算法时可能需要考虑的一些方面,在实际系统中,只能根据具体的VMM结构和虚拟机上运行的应用特点确定一种较优的算法。 3.3.3.12 常见调度算法 以下讨论Xen系统中使用的三种调度算法。 (一)BVT(Borrowed Virtual Time) Stanford大学的Duda等在1999年提出了BVT(Borrowed Virtual Time)调度算法[K.J.Duda & D.R.Cheriton,1999],希望在为实时应用和交互应用提供低延时的同时,根据所有应用的权重来分配CPU资源。该算法在单处理器和多处理器上都有实现。 BVT算法根据virtual time决定VCPU的运行时间,具有最早effective virtual time (EVT)的VCPU可以得到运行。同时延迟敏感的VCPU可以暂时减小virtual time,表现为较早的EVT,从而能够尽快运行。也就是说VCPU可以向将来自己的CPU份额借用virtual time。 每一个VCPU维护一组状态:,其中, Ei表示它某时刻i的EVT Ai表示它实际的virtual time Wi表示它可以借的virtual time warpBacki表示是否允许借virtual time。 当选择下一个要运行的VCPU时,选择Ei最小的VCPU,Ei按照下式计算: Ei = Ai - (warpBacki ? Wi : 0) 若是延迟敏感的VCPU,warpBacki是1,需要从实际的Ai减去一个Wi值,从而能够获得较小的Ei,使得能较早执行。 Xen2.0版本曾经使用BVT算法作为默认调度算法。该算法是一种work-conserving型调度算法,不支持精确的CPU分配。 (二)简单最小时限调度sEDF(simple Earliest Deadline First) EDF(Earliest Deadline First)算法是1970年代提出的一种动态调度算法[C.L.Liu & J.W.Layland,1973],用于实时操作系统中。它将所有任务放在优先级队列中,当发生调度事件时(如任务结束、新任务加入等),从队列中找出时限最短的任务并调度运行。 Xen3.0版本曾经使用sEDF算法作为默认调度算法。sEDF是一种最小时限调度算法,它为每一个VCPU指定周期p和时间片s,表示在p周期该VCPU必须运行s时间;用一个可运行队列(runnable queue)管理所有当前周期内还有可运行时间的VCPU,这些VCPU按照时限递增排列;用一个等待队列(waitqueue)管理当前周期的运行时间已经用完的VCPU,这些VCPU按照下一周期的开始时间递增排列。每次调度时,从可运行队列头取得可以运行的VCPU[S.Diestelhorst,2007]。 sEDF算法同时支持work-conserving和non-work-conserving模式,在non-work-conserving模式下可以精确限定某个虚拟机使用的CPU资源比例,即使没有其他虚拟机运行,该虚拟机也只能使用一定的CPU资源。sEDF并不支持全局(多个CPU情况下)的负载均衡。例如在一台双CPU的主机上,设置CPU1:VM1(80% CPU),CPU2:VM2(80% CPU),则无法为VM3(30% CPU)分配CPU,因为每个CPU都只剩下20%可用。 (三)基于额度的调度(Credit based)[Xen wiki,2007] 该算法能保证在SMP上公正运行。 每个CPU管理一个本地可运行的VCPU队列,该队列根据VCPU的优先级排序,每个VCPU的优先级可能是over或者under,表示该VCPU当前是否已经透支了它应该分配到的CPU资源。当一个VCPU被放入一个运行队列时,将其插在相同优先级的VCPU后面。 一个VCPU运行时,将消耗它的CPU额度(credits)。每隔一段时间,由一个结算线程重新计算每个VCPU消耗了或者获得了多少额度。当额度为负时,则将优先级改为over;直到一段时间以后,额度又积累为正数,则优先级变为under,每结算一次,则运行队列要重排一次。 当一个VCPU的时间片用完或被阻塞时,排在CPU的运行队列头的VCPU将被调度运行。若此时该CPU的运行队列中没有优先级为under的VCPU,则将从其它CPU的运行队列中寻找一个under的VCPU,也就是说,当一个CPU空闲时,将运行等待其它CPU的VCPU。这一策略保证了虚拟机共享整个物理主机的资源,也保证了在整个物理主机环境内所有CPU的负载均衡,也保证了对系统资源的充分利用:当系统中有可运行的VCPU时,不会有任何一个CPU空闲。 Credit调度策略是目前Xen的默认调度策略,Xen允许为每个虚拟机设置两个参数:weight和cap。weight表示虚拟机调度的相对重要性,例如一个weight为512的虚拟机得到的CPU资源是一个weight为256的虚拟机得到CPU资源的两倍;cap是虚拟机可用CPU资源的绝对上限,cap为100表示最多使用一个CPU,50表示0.5个CPU,400表示4个CPU,0表示没有上限。 以上三种调度算法各有特色,目前也有一些研究根据自身应用的特点来设计或改进虚拟CPU的调度。 3.3.4 小结 CPU的虚拟化方法主要有模拟执行和监控执行两种方式,现有的支持多个虚拟机同时运行的VMM通常采用监控执行的方式。监控执行的实现关键是“特权解除”和“陷入-模拟”。 由于x86指令集中存在非特权的敏感指令,因此其CPU虚拟化技术要保证虚拟机执行敏感指令时能陷入VMM,现有的软件虚拟化技术在不同的时机修改客户操作系统以保证这种陷入:二进制代码动态翻译在运行时动态替换二进制代码;半虚拟化在编译前静态修改敏感操作;预虚拟化修改编译器,在编译时对代码进行替换。而硬件辅助虚拟化技术通过扩展指令集保证陷入,无需修改客户操作系统。 利用硬件辅助虚拟化技术能实现较为简洁的“陷入-模拟”的虚拟化,但是现有的硬件辅助虚拟化支持还存在很大的性能改进空间,同时多核化的发展方向为CPU虚拟化提出了划分虚拟化的可能性。未来的发展方向应该是基于硬件虚拟化技术,吸收软件虚拟化技术的经验,实现更高性能的CPU虚拟化,并进一步完善对指令集的硬件虚拟化支持。此外,如何设计一类适合虚拟化环境的虚拟CPU调度算法,或者如何针对虚拟机的应用环境选择一种调度算法,也是亟待研究的问题。 3.4 内存虚拟化 内存虚拟化是虚拟机管理器(VMM)的重要功能之一。由于内存是虚拟机最频繁访问的设备之一,内存虚拟化的效率将对虚拟机的性能产生重大影响。而由于现代计算机通常都采用段页式存储管理、多级页表等复杂的存储体系结构,这又给高性能内存虚拟化的设计带来了很大挑战。 3.4.5 内存虚拟化的基本原理 VMM 通常采用分块共享的思想来虚拟机算机的物理内存。也就是说,VMM 需要将机器的内存分配给各个虚拟机,并维护机器内存和虚拟机所见到的“物理内存”的映射关系,使得这些内存在虚拟机看来是一段从地址0 开始的、连续的物理地址空 间。 3.4.5.13 基本概念 现代计算机通常都具备内存分页保护机制,这给VMM 进行内存虚拟化提供了必要的硬件支持,因为VMM 能够以页面为单位建立虚拟地址到机器地址的映射关系,并利用页面权限设置实现不同虚拟机间内存的隔离和保护。但是,由于客户操作系统本身也会进行页式内存管理,虚拟机与传统计算机相比,其内存系统多了一种地址,共包括以下三种地址: , 机器地址(Machine Address) 指真实硬件的机器地址,即地址总线上应该出现的地址信号; , 物理地址(Physical Address) 指经过VMM 抽象的、虚拟机所看到的伪物理地址; , 虚拟地址(Virtual Address) 指Guest OS 提供给其应用程序使用的线性地址空间。 显然,VMM的内存模块负责完成物理地址到机器地址的映射,我们将这个映射记为f;同时,Guest OS 的内存管理模块要完成虚拟地址到物理地址的映射,我们将这个映射记为g,则虚拟地址、物理地址和真实地址之间的关系如图3-5所示。 图3-5 机器地址,物理地址和虚拟地址 如图3-6所示,两个不同的虚拟机中的进程,分别有一个页表(Page Table)进行地址转换。页表将进程的虚拟地址转换为物理地址。为了将物理地址转为最终使用的机器地址,虚拟机管理器维护着从物理地址到机器地址的真正的页表。在图中,机器页面100、200和400分别被分配给处在不同虚拟机中的两个进程;其它的机器页面也可以被分配给任何一个虚拟机。 进程A进程B 10020050240虚拟地址空间 400700150250物理地址空间 虚拟机1虚拟机2 没有映射到机器页面 100200400机器地址空间 图3-6 虚拟机内的三级地址映射 此时,虚拟机1内的进程A和虚拟机2内的进程B的页表,以及虚拟机管理器维护的从物理地址到机器地址的映射表如表3-1所示。 表3-1 三级地址页表 虚拟页面物理地址虚拟页面物理地址 ------------ 10070050150 ------------ 200400240250 ------------ 虚拟机1中进程A的页表虚拟机2中进程B的页表 物理地址机器地址物理地址机器地址 ------------ 400100150没有匹配 ------------ 700400250200 ------------ 虚拟机1从物理地址到虚拟机2从物理地址到 机器地址的映射机器地址的映射 3.4.5.14 x86的内存寻址机制 下面以x86体系结构为例,对内存寻址机制做简要的介绍。在处理器访问内存时,先通过段选择符和段描述符将指令中的逻辑地址(Logic Address)转换为虚拟地址(或线性地址,Linear Address)。线性地址还需要进一步转换为物理地址,才能真正访问内存中的数据。转换过程如图3-7所示。x86在硬件上支持分页,将内存划分为4KB或者其它大小的页;所以,虚拟地址由虚拟地址页号(page#)和页内地址偏移(offset)两部分组成;同样,物理地址由物理页号(page frame)和页内地址偏移(offset) 两部分组成。页表的作用是将虚拟页号匹配为物理页号(page frame)。当处理器具有一个虚拟地址后,它获取到虚拟地址的页号,然后在页表中相应位置获得相应的物理页号。因为页表存储在内存中,所以处理器访问页表的速度很慢;如果每次转换都要读取页表的话,地址转换将会带来非常大的性能损耗。因此,x86处理器中加入了TLB(Translation Look-aside Buffer),用来缓存已经转换过的虚拟地址。在每次虚拟地址空间切换时,硬件会自动清空TLB。 虚拟地址物理地址CPUpage#offsetpage frameoffset page#page framepage#page frame 4001001023342TLB hit50150...... 7004003--- 2402502--- 250200167 TLB033 TLB miss页表 图3-7 x86内存寻址机制 3.4.5.15 页表虚拟化 对于传统计算机系统,一旦页式存储管理模式被启用,操作系统及其应用程序总是使用虚拟地址来访问计算机的内存。操作系统通过配置多级页表(Page Table)建立虚拟地址到物理地址的映射关系,并把页表的指针载入处理器中的内存管理单元(Memory Management Unit, MMU),由硬件在必要的时候通过查询页表以完成虚拟地址到物理地址的转换。 但是,普通的MMU 只能完成一次虚拟地址到物理地址的映射,在虚拟机环境下,经过MMU 转换所得到的“物理地址”并不是真正硬件的机器地址。如果需要得到真正的物理地址,必须由VMM介入,再经过一次映射才能得到总线上使用的机器地址。显然,如果虚拟机的每个内存访问操作都要由VMM 介入,并用软件模拟地址转换是不切实际的。如何利用现有的MMU 机制实现虚拟地址到机器地址的高效转换,是VMM 在内存虚拟化方面面临的基本问题。 为了实现虚拟地址到物理地址的高效转换,现在普遍采用的思想是: 由VMM 根据映射f 和g 生成复合的映射f • g,并直接把这个映射关系交给MMU。这种思想的可行性在于:1)VMM 维护着映射f ;2)VMM 能够访问Guest OS 的内存,因此能够模拟MMU 来查询Guest OS 的页表,从而能够获得映射g ;3)计算复合映射f • g 能够在恰当的时候高效地进行。 尽管基本思路是一样的,但现有的VMM 针对上述思路分别采取了不同的实现方法。下面,我们将分别讨论其中两个实现方法:MMU 半虚拟化和影子页表。 (一)MMU 半虚拟化 半虚拟化指的是经过VMM 抽象的虚拟机体系结构与实际硬件略有不同,并以此为代价降低VMM 本身的复杂性,同时获得更好的性能的虚拟化方法[Andrew et al.,2002]。由于虚拟硬件的界面与真实硬件存在差异,半虚拟化通常要求修改Guest OS 的少量源代码,使其适应这些差异。 剑桥大学的Xen 系统是采用半虚拟化技术的典型代表,它对CPU、内存以及I/O 设备的虚拟都采用了半虚拟化的思路,使虚拟机能够达到接近于裸机的性能。这里,我们将着重讨论Xen 的内存半虚拟化方法[K.Fraser et al.,2004]。 当Xen 上运行的Guest OS 创建一个新的页表时,会从它所维护的空闲内存中分配一个页面,并向Xen 注册该页面。此时,Xen 就会剥夺Guest OS 对该页表的写权限,之后Guest OS 对该页表的写操作都会陷入到Xen 加以验证和转换。Xen 会对页表中的每一个页表项加以检查,确保它们只映射了属于该虚拟机的机器页面,而且不得包含对页表页面的可写映射。然后,Xen 会根据自己所维护的映射关系f ,将页表项中的物理地址替换为相应的机器地址,最后再把修改过的页表载入MMU。这样,MMU 就可以根据修改后的页表直接完成虚拟地址到机器地址的转换。在实际实现中,Xen 还对页表项的批量更新进行了优化,以避免频繁陷入VMM 所带来的开销。 半虚拟化方法实现简单,Xen 将映射关系f • g 直接写入Guest OS 的页表中,并替换原来的映射g,这实际上已经违背了“f-map 对于虚拟机不可见”的原则[Robert & GoldBerg P,1974]。但是,这种破例在半虚拟化条件下是允许的,因为半虚拟化要求能够获得Guest OS 的源代码,因此认为Guest OS 是可信任的。 (二)影子页表 半虚拟化需要获得操作系统的源代码,因此并不适用于无法获得源代码的操作系统,如Microsoft Windows。在全虚拟化环境中,虚拟地址到机器地址的转换必须使用影子页表(Shadow Page Table)来实现。VMWare Workstation、VMWare ESX Server 以及KVM 都使用了影子页表技术[Carl A.Waldspurger,2002;P.Barham et al.,2003]。与半虚拟化类似,影子页表技术也采取了将映射f • g 直接交给MMU的思路。所不同的是,半虚拟化技术直接将这个映射关系更新到Guest OS 的页表项中,而影子页表技术则是为Guest OS 的每个页表维护一个“影子页表”,并将合成后的映射关系写入到“影子”中,Guest OS 的页表内容则保持不变。最后,VMM 将影子页表交给MMU 进行地址转换。半虚拟化技术与影子页表技术的比较如图3-8所示。 影子页表的引入使得内存虚拟化对于客户操作系统是完全透明的:Guest OS 所能见到的页表内容没有任何变化,也不需要向VMM 注册页表页面,影子页表的分配和维护完全是在Guest OS 之外的VMM 中进行的。这一点对于全虚拟化是至关重要 的,也是在当前硬件条件下进行内存全虚拟化的唯一方法。但是,维护影子页表的开销是很大的。首先是时间开销,由于Guest OS 构造页表时不会主动通知VMM,VMM 必须等到Guest OS 发生缺页时通过分析缺页原因,再为其补全影子页表。此过程中VMM 需要模拟MMU 遍历Guest OS的页表,方能获得Guest OS 所维护的映射关系g,这种间接的手段要比半虚拟化低效很多。 MMU Para-virtualiztionShadow Page Tables f ? gg Guest OSGuest OS f ? g VMMVMM MMUMMU HardwareMachine PagesHardwareMachine Pages Guest Page TableShadow Page Table 图3-8 半虚拟化与影子页表的比较 其次是空间开销,VMM 需要支持多个虚拟机同时运行,而每个虚拟机的Guest OS 通常会为其上运行的每个进程都创建一套页表系统,因此影子页表的空间开销会随着进程的数量的增多而迅速增大,而Guest OS 的进程数量是VMM不可控的。减小空间开销的一种方法是只为当前进程的页表维护影子页表,这样做虽然将空间开销限制在了常数级别,但是却大大增加了上下文切换的时间开销:VMM 需要在Guest OS 的每个进程切换时重构新进程的所有影子页表。在空间开销和时间开销中做出权衡的方法是使用影子页表缓存(Shadow Page Table Cache),即VMM 在内存中维护部分最近使用过的影子页表,只有当影子页表在缓存中找不到时,才构建一个新的。当前主要的全虚拟化VMM 都采用了影子页表缓存技术。 所以,影子页表的主要开销可以归结为保证影子页表跟Guest OS的页表(也称作虚拟页表)之间的同步开销。虚拟机管理器对陷入的处理应当考虑到,操作系统之内由虚拟地址向物理地址的转换和物理地址向机器地址的转换有很大的区别。这两个页表必须保持同步,如果在虚拟页表中没有相应的从某一虚拟地址到物理地址的映射,那么影子页表中也绝对不能有从这一虚拟地址到机器地址的映射。否则,从虚拟机的角度来讲,应该产生page fault的时刻,并不会产生page fault,这就破坏了虚拟页表和影子页表的一致性。而虚拟机对虚拟页表的更新也必须经过虚拟机管理器的确认,进而更新影子页表。另外一点需要注意的是,MMU对影子页表的修改,例如脏位和访问位,也必须更新到虚拟页表中。 有些情况下,虚拟机需要具有连续机器地址的几个页面来进行I/O访问。虽然物理地址对虚拟机来说是连续的,但是通过影子页表映射到机器地址则未必是连续的,这些页表极有可能是散布在整个机器地址空间的。所以,虚拟机管理器需要将一个跨越多个机器页面的I/O请求转换为多个只需要单个页面的I/O请求[J.Smith & R.Nair,2006]。 3.4.5.16 虚拟机和虚拟机管理器的隔离 虚拟机管理器的数据不能被虚拟机访问,因此需要一种隔离机制。旧的x86体系结构并不支持全虚拟化,所以在其上实现内存虚拟化需要修改其上运行的操作系统。如Xen虚拟机管理器使用的操作系统是经修改过的XenoLinux。这种需要修改操作系统的虚拟化方法被称为半虚拟化。每次当操作系统需要一个新的页表时,例如新的进程被生成时,操作系统从自己的物理内存中分配页面作为页表并进行初始化处理,之后提交给Xen虚拟机管理器。这个过程处理器状态需要从虚拟机工作状态切换到虚拟机管理器状态中,处理器进入了更高级的特权级别。为了避免在切换时刷新TLB,Xen将虚拟机管理器的代码和数据置于虚拟内存最高的64M[P.Barham et al.,2003]中,通过段保护实现虚拟机管理器和虚拟机内存的隔离。其地址空间使用如图3-9所示。这最高的64M地址区域不能被虚拟机使用;而且,因为通常x86的ABI(Application Binary Interface,应用程序二进制接口)并没有使用这些虚拟地址范围,所以这项规定并不破坏应用程序的兼容性。 高特权段Xen,高64M Guest OS 应用程序 图3-9 Xen虚拟机管理器的虚拟地址空间 页表的维护需要虚拟机管理器做很多复杂的工作,而段保护虚拟化的实现则比较简单。在每次虚拟机修改其段描述符表时,都经过虚拟机管理器的)保证段的特权级别比虚拟机管理器的低;2)保护虚拟机管理器的虚拟地址范围不被虚拟两点确认:1 机访问。 3.4.6 内存虚拟化的优化机制 为了使虚拟机系统具有更好的伸缩性和可扩展性,在充分保证虚拟机访问内存的性能的前提下,文献[Carl A.Waldspurger,2002]提出了理想的VMM 应该提供以下一些内存管理功能: , 按需取页 只有当虚拟机真正需要的时候,VMM 才将物理内存分配给它,而不是简单地将固定大小的内存空间划分给虚拟机。按需取页能够提高内存资源的利用率。 , 虚拟存储 VMM能够利用交换(Swap)等技术,给虚拟机提供超过实际机器内存大小的内存空间。虚拟机上的Guest OS 能够像运行在裸机上一样,透明地使用VMM 提供的整个“物理内存”。 , 内存共享 VMM应该允许虚拟机之间只读地共享完全相同的内存区域,从而缓解大量虚拟机并发运行时的内存资源紧缺。实现内存共享的重要基础是内存写时复制机制(Copy on Write)。 为了实现上述这些功能,VMM 必须提供某些机制的保障。 3.4.6.17 按需取页与虚拟存储 VMM在负责分配物理内存时,为了维护系统的正常工作,为了更好地满足虚拟机对内存的需求,更加充分地利用内存资源,仅仅把机器内存划分给每个虚拟机的做法是不够的,需要实现虚拟机内存的动态调配。与此同时,VMM还必须周期性地将虚拟机的一部分内存交换到磁盘设备上以回收内存。要达到以上目标,比较流行的解决办法有两种:一是在VMM层实现内存页面的Swap机制;二是在虚拟机之间使用balloon driver的思想。这两种方法在实际上能解决一些问题,但是也有一些自身的缺陷。 在VMM层实现内存页面的Swap机制时,VMM和VM的关系和操作系统与进程的关系相似。VMM从VM所使用的页面中选择一些页面Swap到外存中,然后这些页面就可以被重新分配给别的VM使用。当VM访问被Swap出去的内存地址时,会产生page fault;VMM负责从别的VM中回收一些页面,从Swap区间读取页面内容,然后将设置好的内存页面返回给产生page fault的VM使用。这种方法有可能导致double swap,即相同的内存页面同时被VMM和VM Swap到外存中。因为运行在VM中的操作系统对VMM的Swap机制毫不知情,而且操作系统有着自己的页面Swap机制,所以,在VMM决定将VM的某一页面Swap到外存之后,运行在VM中的操作系统则可能通过自己的置换策略将此页面Swap到外存。如果这种情况频繁发生的话,会严重地降低VMM整体的性能。在具体的实现中,VMM可以随机选取VM的内存页面进行Swap,以获取平均性能。 因为VMM并不能像操作系统一样,能够看到进程的相关信息进而预测物理页的使用情况,使得由于换页而引起的颠簸现象非常明显。为了改进这种情况,VMWare在其ESX Server产品中引入了一种半虚拟化的解决方法。在每个虚拟机中运行一个称为balloon的进程(balloon driver),负责在虚拟机和VMM之间传递内存信息。当VMM需要回收内存时,会给balloon“充气”,也就是由balloon进程向它所在的虚拟机申请更多内存,如果有足够的物理内存分配,则会将可用的物理内存直接分配给balloon,否则,需要虚拟机的操作系统根据内部调页策略将一些页交换出去,并将空下来的物理内存分配给balloon,balloon再把分配到的物理内存给VMM。balloon方法从一定程度上避免了频繁的换页操作。 3.4.6.18 内存共享 现代操作系统和应用程序的尺度越来越大,很大程度上加重了系统的内存负担。在同一台计算机上同时运行多个相同的操作系统或应用程序时,相同的内容却因为没有提供共享机制而不得不保存重复的拷贝。如果虚拟机上运行的操作系统和应用程序大部分相同的话,则可以实现虚拟机间内存的共享,节省内存资源,提高虚拟机的性能。这种情况在实际应用中是普遍存在的,如用于分析系统攻击的Honeypot[Xuxian Jiang & Dongyan Xu,2004]系统。在这样的系统中,在虚拟机管理器之上运行着上百个相同的操作系统,这些操作系统运行相同的应用程序。如果没有内存共享的话,内存的浪费将是非常巨大的。 实现内存共享的核心思想是内存页面的写时复制(Copy on Write)。被共享的页面对所有的虚拟机来说都是只读的,当某一个虚拟机需要修改它时,需要先复制一份页面,然后在复制出的页面上进行修改。通常情况下代码是只读的,所以写时复制可以共享只读的代码和只读的数据,从而节省系统的内存资源。内存的共享使得虚拟机的内存实际占有量变小,因而虚拟机管理器可以分配更多的空闲页面给其它虚拟机使用。 Disco[Edouard Bugnion et al.,1997]实现了透明的页面共享(transparent page sharing)来消除内存页面的冗余性,例如虚拟机间代码和只读的数据。一旦内存页面被共享,虚拟机各自的物理页面则指向相同的机器地址,并且标记为写时复制。任何对其的修改操作会导致page fault,虚拟机管理器从而可以进行复制工作,并将复制出来的页面交付给需要修改页面的虚拟机。 为了进一步提高虚拟机间内存的共享度,VMWare开发了一种叫做基于内容的页共享机制,其中,VMM会跟踪每个物理页的内容,将具有相同内容的页标记出来,并修改影子页表使得他们指向同一个物理页,最后释放冗余的拷贝[Carl A.Waldspurger,2002]。在这里也用到了写时复制(Copy on Write)技术,当要修改被共享的页时,会给写操作的虚拟机分配一个空闲物理页面,将共享页的内容复制到这个空闲页面中并赋予虚拟机该页的写权限。这种基于内容的页共享机制的一个好处就 是共享被充分开发。不论内存被哪个页面使用,还是页面何时被使用,相同内容的页面都可以被共享。另外一个好处则是不需要修改操作系统和应用程序。当然,这种方法会给虚拟机管理器带来额外负担,因为页面需要被扫描才能发现共享的机会。如 2果要将所有的页面都一一比较的话,算法复杂度将会是O(n),这是不可接受的。VMWare ESX Server中使用了哈希(Hash)算法,通过计算并比较每个内存页面的哈希值,减少了内存的比较次数,从而减少了计算量。如果两个页面的哈希值相同,则这两个页面的内容有可能是相同的,此时,完整比较这两个页面中的内容,就可以判断两个页面是否可以被共享。一旦发现页面可以被共享,则Copy on Write机制使得冗余的页面可以被释放。此后,任何试图对共享页面进行修改的操作都会导致page fault,VMM在page fault handler中再透明地复制出一份内存页面供虚拟机修改。 然而,每次的扫描工作都会给整个虚拟化平台带来不必要的开销,并且,某些页面的内容变化会非常频繁。因此,在VMWare的实现里,并不急于比较一个页面是否能被共享。首先,页面的哈希值被计算并且页面被标记做hint。在以后如果发现此页面保存的哈希值和其它页面的相等,则该页面的哈希值被重新计算。如果新的哈希值跟保存的哈希值相等,则意味着页面没有被修改,页面就可以成功被共享。更高层的扫描策略则决定何时进行扫描,扫描哪些页面。 3.4.6.19 内存可写工作集的使用 虚拟机的内存可写工作集(Writable Working Sets)的概念出现在虚拟机的很多应用中,例如虚拟机的迁移(VM Migration)和虚拟机的克隆(VM Clone)。 在虚拟机迁移的过程中,对迁移造成主要性能影响的是虚拟机内存的迁移[C.Clark et al.,2005]。在虚拟机处在工作的状态中时,虚拟机的内存页表不停地被修改。如果完全停止虚拟机进行迁移的话,势必影响虚拟机的服务,而且停止时间和内存的大小成正比。另外一种做法是在虚拟机运行的同时,虚拟机的内存被不断地迁移到目的主机。这会造成某些不断被虚拟机修改的页面将会重复地传送到目的主机,这不但造成了额外的网络负担,而且影响虚拟机的性能。对很多虚拟机来说,有一小部分内存是被更新得非常频繁的,这部分内存不值得在迁移初期就进行处理,而只需在停止源主机上的虚拟机时进行处理即可。 可见,在虚拟机运行过程中,有一大部分内存很少或者从来都不会被修改;而另外的部分则经常被修改。我们把频繁被修改的这部分内存称作内存可写工作集(Writable Working Sets)。获取内存的可写工作集,就可以使得在不修改操作系统代码的前提下,让虚拟机管理器窥得虚拟机内存页面的使用情况。 在虚拟机内存管理中,如何获得内存可写工作集呢,一种获取办法是,将虚拟机中所有的内存页面设置为只读。虚拟机所有对内存的写操作都会引起一个page fault。虚拟机管理器在page fault handler里容许那些原本合法的写操作,并且把该对页面的写操作通过位图(Bitmap)等方法记录下来。这样,在一段时间内那些被修改过的内存页面就被收集起来了。 在虚拟机的迁移和克隆应用中,利用可写工作集能够提高效率。在虚拟机迁移过程中,避免重复地迁移可写工作集,只在停机迁移时传送可写工作集,可以减少停机时间,增加了运行在虚拟机上服务的连续性。在虚拟机克隆中,在父虚拟机和子虚拟机之间构造内存写时复制的机制时,父虚拟机需要停机一段时间。这段时间占父虚拟机总停机时间的绝大部分。在虚拟机克隆中利用可写工作集,就可以在父虚拟机不停机时将内容很少变化的内存页面先行处理,最后停机时只处理可写工作集,就可以达到减少停机时间的目的。最后,如果虚拟机管理器中提供Swap机制,则在选择被置换出的页面时,应该避免置换可写工作集中的页面,因为这些页面既有可能很快又要被访问到。 3.4.6.20 硬件辅助内存虚拟化和其它优化 因为内存虚拟化至关重要,各种虚拟机管理器在具体实现中都要针对内存虚拟化做了相关的优化。与此同时,硬件生产厂商也在试图在硬件级别上提供对内存虚拟化的支持。 Xen虚拟机管理器提供了批量提交Hypercall的机制,减少了修改页表带来的开销。因为内存地址转换需要额外的软件转换方法,另外同时运行的好几个虚拟机增加了处理器地址空间切换的次数,会影响整个虚拟机管理器的性能。在实际中,为了提高运行在虚拟机中应用程序的性能,通常需要考虑更多的方法。在Xen虚拟机管理器中,虚拟机通过Hypercall来更改页表。Hypercall导致虚拟机陷入到Xen虚拟机管理器中,产生额外的资源消耗。为了减少总共所需的Hypercall的数量,虚拟机可以批量提交对页表的修改,这在生成新的地址空间时尤其有益处。然而必须确保这种批量更新足够早,否则会影响地址转换的正确性[P.Barham et al.,2003]。 Intel公司即将在其处理器中增加对内存虚拟化的硬件支持[Darren Abramson et al.,2006]。虚拟处理器标识(Virtual-processor identifiers,VPIDs)容许虚拟机管理器给每个虚拟机分配一个非零的VPID。处理器利用VPID在TLB中标识虚拟地址转换。这项特性防止了每次VM entry和VM exit导致的TLB清空,从而避免了因TLB清空引起的性能损失。Intel公司即将推出的另一个处理器特性是扩展页表(Extended page tables,EPT)。当这项特性激活时,被CR3引用的页表负责将虚拟地址转换为物理地址,另一组页表(EPT)将物理地址转换为机器地址。因此,Guest OS将被容许修改自己的页表并且直接处理页面失效。EPT使得虚拟机管理器避免了虚拟化页表带来的VM exit,这是当前虚拟化主要的开销。 3.4.7 小结 本小节主要讲述了内存虚拟化的基本原理和内存虚拟化的主要优化方法。内存虚拟化的基本原理讲述了机器地址、物理地址和虚拟地址之间的映射关系。另外,也对x86的内存寻址机制进行了概念上的描述。内存虚拟化的核心部分是页表的虚拟化,在本节中介绍了主要的两种方法:MMU半虚拟化和影子页表,以及它们各自的特点。在内存虚拟化的优化机制中,主要介绍了按需取页、虚拟机间的内存共享、内存可写工作集和硬件辅助内存虚拟化。值得一提的是硬件辅助内存虚拟化,以Intel为代表的硬件生产厂商正在设计和实现硬件辅助虚拟化。Intel准备增加虚拟处理器标识(Virtual-processor identifiers,VPIDs),避免了TLB在虚拟机切换时的刷新。另外一个处理器特性是扩展页表(Extended page tables,EPT)。当这项特性被激活时,被CR3 引用的页表负责将虚拟地址转换为物理地址,另外一组页表(EPT)将物理地址转换为机器地址。随着硬件的发展,内存虚拟化将会变得更加简单而且有效。 3.5 I/O虚拟化 由于I/O设备具有异构性强、内部状态不易控制等特点,I/O设备的虚拟化一直是虚拟机技术的难点所在。 3.5.8 当前I/O设备虚拟化的几种方法 目前一些常见的VMM系统针对I/O设备虚拟化分别采用了不同的设计思路,比较典型的有:1)全虚拟化,2)半虚拟化,3)软件模拟(如图3-10所示)。 VMM 需要实现的部分Legacy Guest OSLegacy Driver Legacy DevicePara-virtualized Legacy Guest OSModified GuestVirtual MachineLegacy DriverDriverDevice EmulatorMonitor (VMM) Legacy DeviceI/O InterfaceI/O Interface Virtual MachineVirtual MachineHost OSMonitor (VMM)Monitor (VMM)Legacy DriverVMM DriverLegacy Driver DeviceDeviceDevice 全虚拟化半虚拟化软件模拟 图3-10 几种不同的I/O设备虚拟化模式 3.5.8.21 全虚拟化 VMware ESX Server对网卡、磁盘等关键设备采用了全虚拟化方法[C.A.Waldspurger,2002],客户操作系统看到的是一组统一的虚拟I/O设备。而客户操作系统对这些虚拟设备的每一个I/O操作都会陷入到VMM中,由VMM对I/O指令进行解析并映射到实际物理设备,然后直接控制硬件完成。这种方法能够获得较好的性能,对客户操作系统是完全透明的。但是,由于VMM需要直接控制各种I/O设备,其设计会变得非常复杂,而且无法应对设备的快速更新。 3.5.8.22 半虚拟化 英国剑桥大学的Xen系统采用半虚拟化方法[P.Barham et al.,2003]。这种方法向客户操作系统提供了一个不同于传统I/O设备的虚拟设备界面,因此它需要在客户操作系统中为每个虚拟I/O设备安装一个特殊的驱动程序。该驱动程序负责将客户操作系统的I/O请求传递给特权域(Privileged Domain)。特权域是一个特殊的、具有直接访问物理I/O设备特权的客户操作系统,它解析收到的I/O请求并映射到实际物理设备,最后交给它的设备驱动程序来控制硬件完成(如图3-11所示)。客户操作系统和特权域之间的通信和数据传递需要在VMM的控制下进行[K.Fraser et al.,2004]。 Modified GuestPrivileged Domain Para-virtualized Back-endLegacyDriverDriverDriver XenI/O InterfaceHypervisor HardwareDevice 图 3-11 Xen的半虚拟化结构 在半虚拟化系统中,安装在客户操作系统中的设备驱动称为“前端驱动(Front-end Driver)”,前端驱动通过VMM定义的系统调用来和特权域的“后端驱动(Back-end Driver)”取得联系。后端驱动会检查该请求的有效性,进行虚拟设备地址到物理设备地址的变换。在转换过程中,Backend Driver还要确保没有访问违例,从而保证虚拟机的隔离性和安全性。最后,Backend Driver再进一步通过特权域中的客户操作系统所提供的I/O接口,间接地控制安装在特权域上的真实设备驱动完成对应的请求。类似的,当I/O请求完成时,后端驱动就会收到来自特权域中的操作系统的通知。此时,它将根据这个完成的请求,找到对应的前端发送来的请求,并通过虚拟中断机制响应前端驱动。 Xen通过一个环状队列来实现在普通域和特权域之间传递I/O请求,如图3-12所示。在这个模型中,前端驱动实际上就是请求的生产者和响应的消费者,相反,后端驱动恰好是请求的消费者和响应的生产者。该环状队列实际上是客户操作系统和特权域间的一块共享内存。其实现结构可以用图3-12表示。图中上半部浅灰色区域为客户操作系统已经发送,但还未被Xen处理的请求;左侧深灰色部分代表已被Xen接受,并正在被特权域处理的请求;下半部灰色部分便是已完成的请求,并等待客户操作系统的确认。 图3-12 Xen的环状队列示意 (图片来自[P.Barham et al.,2003]) 为了实现大量DMA(Direct Memory Access,直接内存访问)数据在客户操作系统和特权域之间的高效传递,Xen采用了“授权表(Grant Table)”机制,通过直接替换页面映射关系来避免不必要的内存拷贝(如图3-13所示)。授权表实现了一种安全的虚拟机之间共享内存机制。每个虚拟机都有一个授权表,指明了它的哪些页面可以被哪些虚拟机访问。同时Xen自身存在一个“活动授权表(Active Grant Table)”,它缓存了来自各个虚拟机授权表的活动表项。 图3-13 Xen的授权表机制的一个授权处理流程 (图片来自[K.Fraser et al.,2004]) 当客户操作系统要进行DMA操作时,前端驱动就会给对应的数据页面生成一个“授权描述(Grant Reference,图3-13中GR)”,并把授权描述和请求一起放入前面提到环状队列中。当特权域从队列中取出请求时,就根据授权描述,向Xen请求锁住该页面,以避免DMA过程中该页面被其它客户操作系统替换。Xen接收到请求后,就在活动授权表或客户操作系统的授权表中确认是否已授权特权域访问该页面,并确保没有其它虚拟机能够控制这个页面。如果通过检查,就表明这个页面能够安全地进行DMA操作,特权域在接到Xen的响应后便可以向真实硬件发送DMA请求了。在整个过程中,没有任何页面拷贝,而且授权表机制很好地保证了虚拟机间的隔离性和安全性。 采用半虚拟化的VMM不需要直接控制I/O设备,因此大大简化了VMM的设计。同时,由于半虚拟化的I/O设备驱动将I/O操作在一个较高的抽象层次上直接向VMM传递,因此能够获得很好的性能。而且,半虚拟化还给VMM提供了重新调度、合并I/O操作的机会,甚至在某些情况下还能够加速设备的访问。但是,半虚拟化的代价是需要在客户操作系统上安装驱动程序,甚至修改其代码。 3.5.8.23 软件模拟 VMware Workstation和KVM都采用宿主操作系统(Hosted VMM)结构[J.Sugerman et al.,2001],即它们的VMM实际上运行于一个传统操作系统之上。这类VMM无法获得对硬件资源的完全控制,因此通常用软件模拟的方法来虚拟I/O设备。客户操作系统的I/O操作会被VMM捕获,并转交给宿主操作系统的一个用户态进程,该进程通过对宿主操作系统的系统调用来模拟设备的行为。 软件模拟的方法需要VMM捕获客户操作系统发送给硬件的基本I/O操作。由于某些体系结构(如x86)同时存在统一I/O地址空间和分离I/O地址空间两种I/O模式,这就给VMM的设计带来了一些挑战。 统一I/O地址空间又称为“内存映射I/O(Memory mapped I/O)”,这种模式允许操作系统直接用访存指令和I/O设备交换数据。为了截获此类I/O操作,VMM就必须利用MMU机制对相应的地址空间进行读写保护,这样就能保证客户操作系统对这些地址的访问都能陷入VMM加以处理。有关内存管理和保护的方法详见本章3.3节。对于分离地址空间的I/O操作,VMM就必须陷入并处理每个I/O指令。由于指令系统通常对I/O指令进行了特权级别的保护,这种陷入也是可以实现的。 模拟I/O虚拟化方法的最大开销在于处理器模式的切换:这又包括从客户操作系统到VMM的切换,以及从内核态的VMM到用户态的I/O模拟进程之间的切换。因此对于采用模拟方法进行虚拟化的I/O设备,优化I/O性能的主要策略就是尽量减少模式切换。例如在VMware Workstation中,许多I/O指令都直接在VMM中处理,而只有遇到那些真正会改变物理设备状态的操作,如读写磁盘和收发网络数据包等,才切换到I/O模拟进程中进一步处理,这样就大大减少了从VMM到I/O模拟进程间的切换[J.Sugerman et al.,2001]。 模拟I/O的另一个重要方面是I/O模拟进程的设计。用软件模拟整个计算机平台并不是一件简单的事情。通常,I/O模拟进程需要实现的设备包括:BIOS、PCI总线、时钟控制器、中断控制器、磁盘设备、网络设备、USB总线、VGA适配器、PS2 终端设备。幸运的是,VMM可以利用现有的I/O模拟器实现这些功能,如Qemu等。 模拟I/O设备的方法对客户操作系统也是透明的,而且VMM的设计也非常简单,兼容性很好。但是其性能通常只有上述两种方法的20%,50%[I.Pratt et al.,2005],不适用于服务器等高端应用。 3.5.8.24 三种I/O访问模式的比较 表3-2给出了三种常见的I/O访问模式在性能、实现代价等方面的比较。 表3-2 三种I/O访问模式的比较 全虚拟化 半虚拟化 软件模拟 性能 高 高 低下 透明性 透明 不透明 完全透明 高,但可利用现有的硬件实现代价 高 一般 仿真技术,如QEMU 可移植性 高 低 一般 需要注意的是,上述分类和评价并不是绝对的。在一个现实系统中,我们通常采用几种虚拟化技术相结合的方式来实现整个I/O系统的虚拟化,从而做到优势互补。例如,对于主要采用软件模拟的VMM,可以对一些关键的设备,如中断控制器、时钟控制器等采用全虚拟化的方法以提高性能。而在以半虚拟化为主的VMM中,也常用软件模拟的方法来虚拟终端等一些低速的I/O设备。 3.5.9 虚拟机的直接I/O访问 在以上几种方式下,虚拟机(VM)的每一个I/O操作,都要由虚拟机管理器(VMM)或者特权域(Privileged Domain)的介入和协助方可完成。这已经成为了制约虚拟机性能和功能的瓶颈所在,尤其是对于那些I/O吞吐量很大的应用,如Web服务器、数据库服务器、个人多媒体应用等。 首先是性能瓶颈。以Xen系统为例,尽管在通常情况下它对CPU和内存的虚拟化效率能够达到裸机的90%以上[B.Clark et al.,2004]。但是有研究表明,当运行类似Web服务器这样I/O密集的应用时,仅仅用于支持网卡半虚拟化的CPU负担就高达总CPU时间的30%,35%,尤其是当传输大量KB级别的小文件时[L.Cherkasova & R.Gardner,2005]。特别的,如果系统安装了某些智能网卡,由于虚拟的网络设备无法利用网卡本身所具有的协议分段、校验码计算等功能,实际的I/O吞吐量可能只有裸机的20%左右[A.Menon et al.,2005]。 其次是功能瓶颈。由于上述I/O虚拟化方法通常只能提供一些传统的硬件界面,即客户操作系统所见到的虚拟I/O设备只具有最基本的功能。这使得虚拟化技术在个人多媒体计算领域的应用受到了很大限制,例如,虚拟机用户将不能获得具有硬件3D加速功能的显示适配器,尽管该设备在物理硬件系统中确实存在。 为了解决上述问题,近年来学术界提出了另一种I/O虚拟化方法:虚拟机的直接I/O访问。它的主要思想是:可控地将某些物理I/O设备分配给指定的虚拟机,让虚拟机能在无需VMM或特权域介入的情况下直接访问该设备[D.Abramson et al.,2006],从而解决上述提到的I/O设备虚拟化所遇到的性能及功能瓶颈,同时降低VMM设计的复杂性(如图3-14所示)。 Device DriverLegacy Guest OS Virtual MachineDevice Monitor (VMM)Management Device 图3-14 虚拟机的直接I/O访问 2006年IBM基于Xen实现了InfiniBand设备的直接I/O访问[J.Liu et al.,2006]。它虽然沿用了Xen的半虚拟化结构,即大部分设备控制(如初始化等)仍然由特权域代理完成,但是允许客户操作系统直接对该设备执行一些性能敏感的I/O操作,如数据发送和接受。实验表明,这种方法能够获得接近裸机的I/O吞吐量和访问时延,而且其主要开销在于不可避免的VMM和虚拟机之间的I/O中断传递。 与此同时,佐治亚理工大学提出了I/O设备自虚拟化(Self-Virtualization)的概念[Himanshu Raj et al.,2006],有别于VMM为每个虚拟机虚拟一组I/O设备的传统思想,自虚拟化方法希望设备本身能够虚拟出多个抽象界面,并直接提供给不同的虚拟机使用。他们针对网卡设备考察了多种实现方案,并基于Xen,在IXP2400网络计算机上实现了其中一个原型。实验表明,由于减少了特权域的介入,一个虚拟网卡的吞吐量相对Xen本身提高了77%,而时延则降低了53%。同时他们认为,若能充分利用多核CPU的计算能力,多个虚拟网卡的加速比并不会有太大的下降。 但是,直接I/O访问的方法也面临一些挑战。第一,I/O设备进行DMA操作时必须使用真实的硬件物理地址,而这是客户操作系统无法获得的。更加糟糕的是,某些不受信任的客户操作系统还可能利用DMA绕开MMU的内存保护机制,访问属于其他虚拟机的内存。第二,VMM仍然要维护硬件的中断向量表,并向虚拟机转发中断,以保证对计算机其它部分的控制,这仍然存在不小的开销。第三,采用了直接I/O访问后,所有虚拟机所能得到的虚拟设备总数将不可能多于真实的物理设备数量,这种限制将大大丧失虚拟化技术的优势[Muli Ben-Yehuda et al.,2006;M.Mahalingam,2006]。 针对以上问题,直接I/O访问的研究涉及到两个重要的方面:隔离和共享。隔离,指的是当属于某个虚拟机的I/O设备在进行DMA操作时,必须限制它访问属于其他虚拟机的内存,以保证虚拟机之间的隔离性和安全性;共享,指的是一个物理设备应该能够提供多个抽象的界面,以供不同的虚拟机同时使用,从而降低硬件的冗余配置。 隔离性和共享性可以从硬件层次上解决。当前,主要的硬件厂商和组织都分别提出了相关的技术规范,最具代表性的有Intel的VT-d技术、AMD的IOMMU(Input/Output Memory Management Unit)技术以及PCI-SIG的IOV(I/O Virtualization)规范。 VT-d和IOMMU技术旨在保证虚拟机I/O地址空间的隔离性,并提供硬件中断转发机制[Intel,2007b;AMD,2007]。它们的共同思想是,在PCI总线桥上安装一个类似传统MMU的地址转换设备,并通过I/O页表机制给每个DMA设备提供一个线性地址空间,称为总线地址(如图3-15所示)。总线地址能够以页面为单位映射到物理地址。为了提高地址转换的效率,IOMMU通常还带有自己的IOTLB(Input/Output Translation Look-aside Buffer)。 CPUCPU North BridgeDRAMIOMMU / VT-d PCIe Root Ports Device 图3-15 IOMMU的体系结构 在IOMMU规范出现之前,主流操作系统和VMM都提供了类似的隔离保护机制。如Linux的SWIOTLB和Xen的Grant Table都可以看作是软件模拟的IOMMU。目前,IBM、Intel和AMD正在共同扩展Linux和Xen,研究使其支持硬件IOMMU的有效方案[Muli Ben-Yehuda et al.,2006]。他们指出,在真正支持IOMMU的硬件面世之前,仍有许多问题需要进一步探索和完善,例如虚拟机的快照和迁移等功能可能将无法使用。 PCI-SIG的IOV规范包括ATS(Address Translation Services)、SR(Single Root IOV)、MR(Multi-Root IOV)三部分,旨在定义一个可分割共享I/O设备的规范[PCI-SIG,2007],按该规范设计的PCI-E设备具有统一的、可分割共享的界面。 3.5.10 小结 I/O设备的多元化和异构性使得I/O虚拟化成为虚拟化技术的难点。但是,商业服务器等很多应用领域,又对虚拟机的I/O功能和性能提出了很高的要求。目前一些常见的VMM系统分别采用了不同的I/O虚拟化设计思路,比较典型的有全虚拟化、半虚拟化和软件模拟。这三种技术各有其优势与缺点,真实的系统则往往采用几种虚拟化技术相结合的方式来实现整个I/O系统的虚拟化。 为了解决I/O虚拟化所面临的性能瓶颈和功能瓶颈,近年来学术界又提出了虚拟机直接I/O访问的思想。直接I/O访问允许VMM可控地将某些物理I/O设备分配给指定的虚拟机,让虚拟机能在无需VMM或特权域介入的情况下直接访问该设备,从而在消除上述瓶颈的同时降低VMM设计的复杂性。直接I/O访问涉及到隔离和共享两个重要方面,这通常需要通过软硬件协同设计的方法来解决。当前,国际主流硬件厂商和组织都分别提出了针对I/O设备分割共享和虚拟机直接I/O访问的相关技术规范。 3.6 操作系统适配 操作系统适配技术是研究在虚拟化环境下,如何修改操作系统使得整个虚拟化环境的性能得到提高、功能得到增强的技术。操作系统适配技术的目的主要有三类:1)将操作系统移植到虚拟环境下,并且能最大程度地提高其性能;2)当执行虚拟机监控管理功能时,能够从客户操作系统内部获得支持;3)为某种特定的应用场景定制操作系统。下面分别说明这三类技术的特点和方法。 3.6.11 迁入虚拟化环境 为迁入虚拟化环境而进行的操作系统适配涉及到两方面:第一,某些虚拟化环境,要求客户操作系统必须经过修改才能在其上正确地运行,比如半虚拟化的环境;第二,为了提高虚拟机性能或者虚拟化环境的整体性能,对客户操作系统或者宿主操作系统进行修改。下面将依次对这两个方面介绍。 3.6.11.25 将OS移植到VMM中 “全虚拟化”(full virtualization)[P.Barham et al.,2003]方法最显而易见的好处在于操作系统可以不经任何修改就直接在虚拟硬件上运行。但在x86体系结构下,全虚拟化一般采用动态二进制翻译机制来实现虚拟化,效率比较低。而半虚拟化效率则要高得多,在理想情况下,几乎可以达到裸机的性能。但要正确实现x86体系结构的半虚拟化,VMM就必须能够对“敏感指令”进行操作[P.Barham et al.,2003]。而客户操作系统在没有足够特权的情况下执行这些敏感指令会导致“沉默的失败”(fail silently,即如果特权级不够,那么会直接导致执行失败,不会产生其它响应),并非产生一个便于VMM使用的陷入(trap)。这就需要对操作系统进行适当的修改。 下面将以Xen为代表,描述半虚拟环境中操作系统在存储、CPU和I/O管理等方面所需要做的更改。 (一)存储管理 VMM管理了硬件机器上的所有内存,这些内存称为机器内存。虚拟机需要自己的连续的内存,从页面0开始直到页面n,称为物理内存。VMM根据虚拟机对物理内存的需求,分配相应的机器内存,映射为虚拟机的物理地址。每个虚拟机对应一个物理内存页面到机器内存页面的映射表,简称P2M(Physical to Machine)表,而VMM则维护了一个全局的机器页面到物理页面的映射表,简称M2P(Machine to Physical)表。如图3-16所示,有两个虚拟机Domain1和Domain2,Domain1的三个从0开始连续标号的物理内存页面,通过P2M表映射为机器页面,Domain2也有同样的映射。而VMM存在一个M2P表,根据机器页面标号就能找出物理页面标号。物理页面不一定要映射连续的机器页面。 Domain 1Domain 2 AppAppAppApp AppApp P2MP2M M2P Virtual Machine Monitor 图3-16 物理页面和机器页面的映射 因此,内存的寻址变为两级映射:虚拟机虚拟地址-虚拟机物理地址-机器地址。x86体系结构的MMU目前只支持一次映射,需要由软件实现两级转换。已有的内存虚拟化方式主要有影子页表和直接页表访问(MMU 半虚拟化)两种方式(参见3.3节),两种方式在Xen中均有实现。影子页表的方式不要求客户操作系统做相应的修改,硬件内存资源对于虚拟机是透明的,这种方式有利于全虚拟化。直接页表访问的方式需要修改操作系统:在该模式下,M2P表由客户操作系统维护,客户操作系统的页表直接完成虚拟地址-机器地址的映射,硬件MMU直接遍历客户操作系统的页表完成寻址,只有当需要更新页表时,才需要由虚拟机管理器进行确认。 (二)CPU管理 CPU虚拟化对客户操作系统提出了几个要求。因为虚拟机管理器运行在操作系统的下层,这违背了惯常的关于操作系统在整个系统中特权最高的假设。为了保护虚拟机管理器不会受到操作系统不正确行为的影响(即一个虚拟机不受另一个虚拟机的影响),客户操作系统就必须被改造为能够运行在较低的特权级上(参见3.2节)。 例如在x86体系结构上,将操作系统改为运行在ring 1特权级上即可。这就防止了客户操作系统会直接执行虚拟化所需的特权指令,也保证了操作系统与运行在ring 3上的应用程序之间相隔离的安全性。 将客户操作系统移植进入半虚拟化环境中,主要做以下修改: 首先是对特权指令的处理。客户操作系统的特权指令需要被虚拟机管理器确认和执行。因为只有虚拟机管理器有足够高的特权级来执行这些指令,任何客户操作系统试图直接运行特权指令都会失败,后果要么是“沉默”要么是产生错误。修改客户操作系统,将一个特权指令替换成一个Hypercall,这类似于操作系统中的系统调用。通过调用Hypercall,客户操作系统能够把控制权转移到虚拟机管理器。例如,一个更新页表的操作,被替换为一个Hypercall,运行时,通过Hypercall陷入到VMM中,由虚拟机管理器确认并完成,再把控制权返回给产生本次调用的虚拟机,具体修改方式参见3.2节。 其次是对中断的处理。在Xen的虚拟化机制中,中断只能被虚拟机管理器捕获,并且以事件的方式异步地发送给客户操作系统。客户操作系统需要通过Hypercall的方式向虚拟机管理器注册事件处理函数(event handle)[P.Barham et al.,2003]。当事件发生时,虚拟机管理器会异步地调用该事件处理函数。客户操作系统还可以通过Hypercall的方式清除掉对事件通道(event channel)中相应位的屏蔽,以及清除事件通道中相应的标志位,以便接受下次事件。 (三)I/O设备管理 I/O设备的虚拟化主要包括I/O接口的虚拟化和硬件中断的虚拟化。与全虚拟环境下仿真现有硬件设备不同,以Xen为代表的半虚拟化技术中,VMM和特权操作系统(特权虚拟机)给客户操作系统暴露了一套简单又有效的抽象设备接口[P.Barham et al.,2003](参见3.4节)。Xen将I/O设备访问权限指派给特权虚拟机,该特权虚拟机能够直接访问物理设备,并向其他虚拟机提供物理设备的软件接口,其他虚拟机使用这个软件接口间接访问设备。作为硬件中断的一种替代和模拟,Xen支持轻量级的事件传递机制,用于在虚拟机之间传递中断(event channel)。该方式使I/O设备驱动运行在客户操作系统中,降低了VMM的复杂性,同时I/O操作绕过了VMM,保证了访问性能。于是,对客户操作系统的修改主要分为两个部分: 首先是对I/O接口的虚拟化,这只需在客户操作系统中安装“前端驱动(Front-end driver)”即可。 其次是对硬件中断的虚拟化,上一部分CPU虚拟化中对中断的处理已经包含这些内容,这里不再赘述。 图3-17说明了一次磁盘读取的处理过程。特权虚拟机(Domain0)直接访问物理磁盘,并对其他虚拟机(DomainU)提供一个虚拟块设备(Virtual Block Device,VBD)抽象,其它虚拟机向VBD的前端驱动(Front-end driver)提交磁盘I/O请求,前 特权虚拟机之间的共享环上(参见3.4节),特权虚拟机的后端驱动(Back-end driver)获得请求,端驱动将请求放到该虚拟机和 并将请求转换为实际的物理磁盘I/O请求,经合法性确认后,提交给磁盘驱动设备处理,请求处理完成后再通过事件机制通知 发起请求的虚拟机。 为了提高性能,Xen采取了一些优化措施。首先,Front-end提交请求前,先合并相邻的磁盘请求。Back-end收到各DomainU的磁盘请求后,根据round-robin规则调度各VBD,再根据物理磁盘实际情况利用电梯算法等重排序磁盘请求。最后,使用DMA直接将磁盘数据传输到发起请求的DomainU的内存页面,避免了数据的多次复制。 Domain 0Domain U BackendApplication DeviceFrontendDriver Event ChannelVMM DMAMemoryDisk 图3-17 一次读取磁盘的处理过程 (四)移植OS到Xen的代价 从表3-3可以看出Linux和Windows XP移植到Xen上需要修改的代码量是非常小的[P.Barham et al.,2003]。当前Xen公司移植的Linux可以顺畅运行,但是移植的Windows XP缺乏虚拟的I/O驱动。基于这个原因,表中就没有给出和Windows XP的虚拟设备驱动相关的数据。无论怎样,和Linux一样,我们可以想见这些驱动应该是小且简单的,这得益于Xen提供的理想的硬件抽象。 表3-3 修改Linux 和Windows XP的代码量比较(单位:行) 操作系统的部分 Linux Windows XP 体系结构无关部分 78 1299 , 484 虚拟网卡驱动 , 1070 虚拟块设备驱动 3321 1363 Xen相关部分(非驱动) 4620 2995 总计 (占x86相关代码量的百分比) 0.04% 1.36% 3.6.11.26 提高虚拟化性能 上一节所述的操作系统移植思路和方法,使得Linux、Windows XP等主流操作系统可以运行在半虚拟化环境中,但是还是存在很多的性能问题。这里主要关注如何提高设备虚拟化的整体性能。设备虚拟化的性能代价主要由几个因素决定:一是虚拟机与虚拟机管理器切换的开销;二是虚拟机与虚拟机管理器切换的频率;三是虚拟机管理器进行监控和模拟的效率。 除了提高虚拟机管理器本身的效率之外(参见3.2、3.3、3.4节),通过操作系统的适配技术也能够从降低切换频率和简化监控模拟两方面改进虚拟化性能。 (一)减少环境切换开销 环境切换是指处理器从一个进程或者线程切换到另外一个进程或者线程。进程和线程的切换需要保存原来的状态和获取新的状态。保存和获取的内容包括program counter、通用寄存器、段寄存器、CR3以及页表结构、FPU/MMX寄存器、SSE寄存器和其它内容。因为环境切换需要改变大量的数据,需要花费不菲的处理器时间,所以它是操作系统里开销最大的操作。 J. Sugerman等在VMware环境下进行了客户操作系统(Linux,内核为 2.2.17)的进程切换试验,实验表明,在页表切换上花费大约8.5%的系统开销。因此,他们提出通过修改Linux内核的环境切换函数,使得客户操作系统切换到空闲进程时不用切换页表,这样MMU由于虚拟化产生的开销就减少了一半[J.Sugerman et al.,2001]。这是因为Linux2.2的空闲进程是一个内核进程,使用的是内核页表。而内核页表包含在所有应用程序的页表之中,所以在切换出或者切换入空闲进程时没必要切换页表。这个优化的前提是空闲进程不会修改用户内存部分。这是一个合理的要求,因为空闲进程在可信的内核层次上运行。 此外,在虚拟机管理器之上,环境切换还包括从客户操作系统切换到虚拟机管理器,这往往需要更多的开销。在Xen环境下,修改后的客户操作系统是通过Hypercall陷入到虚拟机管理器中的,此时,虚拟机管理器需要保存客户操作系统当前的状态,读取虚拟机管理器的状态,执行有关特权指令,然后再恢复客户操作系统。所以,如果减少了客户操作系统环境切换的次数或者降低单次客户操作系统环境切换的开销,就能够提高整个虚拟机的性能。 在减少环境切换次数方面,客户操作系统可以通过批量工作的方式,在一次调用中执行一系列的Hypercall。当然,这需要虚拟机管理器提供相应的支持,例如,Xen就提供了multicall(void *call_list, int nr_calls)接口,支持客户操作系统在调用时批量发送Hypercall的机制[P.Barham et al.,2003]。 在降低单次客户操作系统环境切换开销方面,可以采取延迟保存和恢复FPU状态的策略。Xen已有的优化策略[The Xen Team,2006]即是如此。在环境切换时,虚拟机管理器容许虚拟机设置CR0控制寄存器里的TS位;这就意味着在以后尝试使用FPU时处理器会产生一个陷入,客户操作系统在处理陷入时再读入FPU的状态,这样来避免环境切换开销。 (二)提高I/O设备虚拟化性能 通常情况下,由于I/O设备具有异构性和内部状态不容易控制等特点,各种虚拟化平台一般只会提供给客户操作系统虚拟的I/O设备(参见3.4节)。而I/O操作的模拟将带来较大的代价,于是I/O设备虚拟化的性能成为了虚拟化平台的性能瓶颈,因此提高I/O设备的性能也尤为重要。提高I/O虚拟化性能的方式很多,而通过修改客户操作系统来提高性能主要有以下几种思路: (1)减少I/O操作的CPU开销 每个I/O操作会不可避免地带来多次中断,对于每次中断,客户操作系统的中断处理函数会按部就班地发出若干条指令去访问虚拟PIC(Programmable Interrupt Controller),但访问虚拟PIC并不会发生场景切换,所以实际上可以修改中断处理函数,将中断处理函数中的PIC访问部分用精简的指令替换,达到优化目的。 VMware Workstation就是根据这种思路对Linux客户操作系统的中断处理函数进行了修改[J.Sugerman et al.,2001]。据实验统计,未修改以前的客户操作系统访问虚拟PIC的时间占VMM(Hosted架构,参见3.1节)时间的2.5%。以网络I/O为例,当网卡满负荷工作时,会达到每秒100MB的流量,大约会收到8000个包,这使得VM会收到大量的中断,并且对于每个中断,客户操作系统(RedHat 6.2 Linux,2.2.17 kernel)的中断处理函数会向虚拟PIC发送5次访问请求。5次访问请求中,有1次是关于内存方面的,可以将它用MOV等指令内联;其他4次访问产生的效果是使得虚拟PIC只是用非常普通的方式计算了自身的内部状态,可以用具有同样功能的指令代替它们,以达到进一步优化。 (2)优化客户操作系统的驱动 某些虚拟化平台上,客户操作系统可以使用原有的设备驱动来进行I/O访问,这样可以带来便利性,但会产生很多I/O相关 为客户操作系统提供专门的优化驱动程序。当然,这种优化设备驱动指令和中断。为了追求更高的性能,可以针对虚拟化平台 的方法也有其的缺点,它将使得每种设备都需要针对不同的客户操作系统编写不同的驱动。所以这个方法只是一种备选方案,但它比较适用于服务器操作系统这类强调性能并且设备有限的操作系统上。 实际上VMware就是根据这种思路实现了针对服务器的vmxnet网卡驱动。未修改的标准Linux pcnet32网卡驱动在发送一个数据包时,会发出12条I/O指令并收到1次中断。在vmxnet实现中,当需要发送数据包的时候,会发出1个OUT信号,而不是1个中断;当空间足够发送一组数据包的时候,只会收到1个中断;当需要为收发数据包申请空间的时候,使用简单的策略,而不是为追求灵活性而太过复杂的策略。 (3)客户操作系统直接I/O访问 前面两种对客户操作系统的修改,都是在客户操作系统使用虚拟I/O设备这个前提下的优化方法。近年来学术界提出了另一种I/O虚拟化方法:虚拟机的直接I/O访问(参见3.4小节)。它的主要思想是:可控地将某些物理I/O设备分配给指定的虚拟机,让在虚拟机上运行的客户操作系统能在无需VMM或特权虚拟机介入的情况下直接访问该设备[D.Abramson et al.,2006],从而解决上述提到的I/O设备虚拟化所遇到的性能及功能瓶颈,同时降低VMM设计的复杂性。 2006年IBM基于Xen实现了InfiniBand设备的直接I/O访问[J.Liu et al.,2006]。它虽然沿用了Xen的半虚拟化结构,即大部分设备控制(如初始化等)仍然由特权虚拟机代理完成,但是允许客户操作系统直接对该设备执行一些性能敏感的I/O操作,如数据发送和接受。实验表明,这种方法能够获得接近裸机的I/O吞吐量和访问时延。 3.6.12 支持虚拟机管理 操作系统适配包括修改客户操作系统,以便虚拟机的自管理。虚拟机自管理指虚拟机能够根据自身资源使用和负载情况,决定自己的行动,比如迁移和复制。 3.6.12.27 自迁移(Self-migration) 迁移是将虚拟机的运行状态在两台物理主机之间转移。根据应用场景不同,需要支持虚拟机停机迁移、在线迁移等模式。停机迁移指暂停虚拟机的运行,迁移虚拟机的状态,包括CPU状态、内存数据和磁盘数据等,在目的主机恢复虚拟机的运行;在线迁移指迁移时虚拟机绝大部分时间保持运行状态,由于迁移引起虚拟机停机时间在秒级甚至毫秒级,虚拟机用户几乎感觉不到迁移过程的影响。迁移需要解决的关键问题是数据的完整性、一致性,迁移的效率和资源控制。 通常的虚拟机迁移,都是在VMM的控制下完成的。而丹麦哥本哈根大学的研究组则实现了客户操作系统的自迁移(基于Xen)[Jacob G.Hansen & Eric Jul,2004],这种迁移方式没有虚拟机管理器的介入。 在传统的checkpoint算法[Espen Skoglund et al,2000]中,被checkpoint的对象和checkpoint的发起者是不同的两个对象,被checkpoint的对象需要向发起者提交控制权,以便发起者能够暂停它。在自迁移系统中,被checkpoint的对象和checkpoint的发起者是同一个,所以这两个角色同时运行,于是就不能像传统迁移那样传输最终状态(因为传输这个工作本身就会干扰已经获得的最终状态)。 自迁移的实现方法[Jacob G.Hansen & Eric Jul,2004]如下:向guest Linux内核中添加一个迁移线程,该线程对目的主机打开一个TCP 连接,拷贝所有内存页面;在此期间guest Linux其余线程继续工作,并且所有的内存页面写操作采用resend-on-write的方式(参考图3-18),即将改变的页面发送到目的端,同时确定出工作集合(working set patches)[Espen Skoglund et al,2000];保存CPU状态并发送给目的端(此操作执行时,内存使用Copy on Write的方式),resend-on-write阶段结束。此时目的端有一个部分的checkpoint,CPU状态和内存状态是不同步的,剩下的脏页面保存在源端。最后,将这些脏页面拷贝到目的主机,此时目的主机的状态为源端resend-on-write阶段结束时的状态,目的主机开始运行,最后在源端阻塞迁移线程,迁移完成。 由于自迁移是在客户操作系统中发起的,所以比如网络协议和安全特征的选择权就交给了客户操作系统,这样就不需要实现普适的标准。同时,由于没有虚拟机管理器的介入,所以整个过程对虚拟机管理器的依赖很小,于是理论上客户操作系统可以在不同的虚拟机管理器之间迁移,甚至可以迁移到物理主机上。此外,由于自迁移技术自身的隔离性,它可能在可信虚拟平台上会有长足发展。 阶段结束时阶段结束时阶段名源端状态目的端状态 resend-on-writeCPU 阶段1:状态:1 发送变化内存,内存内存找出工作集合状态:1状态:1 resend-on-writeCPUCPUCPU阶段2:状态:2状态:2状态:3保存CPU状态并 发送(此时内存内存内存内存使用COW方式)状态:1状态:3状态:2 CPUCPUCPU将COW保存的状态:2状态:2状态:4内存状态CPU和内存状态 发送给目的端均为resend-on-内存内存内存write结束时状态状态:2状态:4状态:2 图3-18 源端和目的端在自迁移的各个阶段的状态 3.6.12.28 自复制(Self-clone) 所谓虚拟机复制是指从一个运行的虚拟机中复制出另一个运行的虚拟机,两个虚拟机的软硬件配置完全相同。通常虚拟机复制在同一个物理主机上完成。与虚拟机迁移相似,虚拟机复制的内容包括CPU状态、内存数据和磁盘数据等。 Xen目前现的虚拟机复制是在无写时复制机制的情况下,通过完整复制虚拟机状态实现的。这种复制方法不仅需要耗用大量的资源和时间,还必须在复制过程中长时间暂停源虚拟机从而导致其上的服务间断。在Potemkin项目[Michael Vrable et al.,2005] 中,实现Xen虚拟机复制时采用了写时复制机制,但复制过程中仍需挂起源虚拟机。 与虚拟机迁移一样,通常虚拟机复制同样在VMM的监控下进行。受自迁移(Self-migration)启发,可采用类似的方法实现虚拟机自复制(Self-clone)机制。 3.6.13 为特殊项目定制 操作系统适配技术还涉及到研究适用于虚拟机的操作系统技术,使操作系统不再面向所有应用程序,而是与特定的应用程序紧密联系,只为单一应用提供个性化的系统服务。本小节和下一小节将针对该问题进行讨论。本小节讨论的是为特定项目而的定制的操作系统,下一小节则是讨论适用于应用程序的操作系统。 在一些应用虚拟机的试验项目中,根据应用场景的特点,需要对客户操作系统专门定制,比较典型的例子有Denali和Potemkin。 Denali[A.Whitaker et al.,2002]是华盛顿大学研发的专注于提供网络服务的虚拟机项目,它能在一个独立的x86体系结构的物理机器上运行数量众多(大于800)的轻量级虚拟机,执行和检测不可信的指令,其系统结构如图3-19所示。该项目中的客户操作系统Ilwaco是为Denali项目专门开发的轻量级的操作系统。 AppAppApp... GuestGuestGuestDenali virtual...OSOSOSmachine interface Denali isolation kernel x86 arch. interfacex86 hardware 图3-19 Denali系统结构 Potemkin[Michael Vrable et al.,2005]是新一代的基于虚拟机架构的蜜罐(honeypot)系统,其系统结构如图3-20所示。在以往的基于虚拟机的蜜罐系统中,需要预先配置一定数量的虚拟机处于等待状态,等待病毒攻击到来时再唤起一个虚拟机接受攻击,这不仅造成一种计算资源的浪费,而且当已有虚拟机耗尽时,无法立即响应新的需求,而预先部署过多的虚拟机并不可取。Potemkin项目采用虚拟机快速复制技术,蜜罐系统中只需预先部署一个虚拟机,发现有病毒活动时,根据需要实时快速地复制出新的虚拟机并投入运行,这种做法取得了很好效果,而此项目中使用的客户操作系统是经过精简的Debian GNU/Linux 3.1。 Physical Honeyfarm Servers Global Internet Gateway VMM GRE TunnelsVMVMVMExternal IP Routers VMVMVM 图3-20 Potemkin系统结构 一般操作系统定制都是通过修剪操作系统实现(例如重新配置编译Linux操作系统内核)。当前流行的Linux各种版本,其内核中的各种功能模块都是以Module的形式连编,以便替换或剔除。一个内核短小精悍的操作系统更容易保证其稳定性和性能,因此在编译内核时,一般都趋向于“将内核编得尽量的小”。用户可以在/usr/src/linux目录下输入下面的命令: make menuconfig 屏幕将显示内核编译控制界面,如图3-21所示。 图3-21 Linux内核配置页面 根据需要选择必要的模块,然后退出,编译即可得到一个精简版的Linux内核。若修改项比较高级,具体注意事项还需查看专门的手册,这里不再赘述。 3.6.14 虚拟装置(Virtual Appliance) 虚拟装置(Virtual Appliance)是在操作系统上预先安装好应用程序的“应用程序,操作系统”套装软件[C.Sapuntzakis et al.,2003;Virtual Appliance,2007]。虚拟装置的优点在于既然软件已安装到操作系统上,那么所有的配置设置,都可以由软件商预先进行,软件商甚至可以把操作系统内非必要的组件移除,以优化系统,无须用户自行调校,便可取得最佳效果。也就是说,这里的操作系统,是适用于应用程序的特殊操作系统。把虚拟装置安装到虚拟机上,就可直接使用应用程序,不再需要经历各种专业复杂的安装配置以及调试过程。 图3-22展示的是一般大中型企业内部的服务器配备状况,不同的应用和服务都运行在一台单独的物理主机上,以保证易维护性和可靠性。图3-23展示的是企业在采用了“虚拟装置+虚拟机管理器”的解决方案后,将原单独运行的应用和OS打包成“虚拟装置”运行在安装了虚拟机管理器的服务器上。从图3-22和图3-23的对比中,可以看到体系结构的变化以及带来的便利之处。 BeforeFirewall Appliance VOIP Appliance SPAM Appliance Premises Security Appliance Antivirus Appliance Search Appliance XML Appliance 特定的服务/应用对应一台设备Data Integration Appliance 硬件种类繁多,不易维护NAS Appliance硬件利用率较低 2 U 8 U 图3-22 未采用虚拟化技术的服务器 AfterFirewall Appliance VOIP Appliance SPAM Appliance Premises Security Appliance有效节省能源和空间 硬件种类单一,易维护Antivirus Appliance硬件利用率较高Search Appliance XML ApplianceVirtualization Layer Data Integration Appliance NAS Appliance 图3-23 采用“虚拟装置+虚拟平台”的服务器 创建虚拟装置的原则是完全封装。虚拟装置要求所有的组件运行在一个虚拟层上,在制作虚拟装置前,需要对这些组件做好配置,使它们能正确运行并且性能达到最优。由于虚拟装置是针对某个具体应用的解决方案,所以用户没有必要拥有虚拟装置中操作系统的管理员权限,甚至在某些应用中,用户完全没有必要访问虚拟装置内部。当然,最好的方式是,在虚拟装置中配置一个“浏览器/服务器”模式的界面,用户通过浏览器的方式登录使用,以这样的方式来达到限制用户对虚拟装置访问的目的。创建虚拟装置的主要步骤包括以下五步: (一)优化操作系统 创建一个虚拟装置和创建一个物理装置所遵循的原则基本相同,但是虚拟装置没有事先安装在任何物理硬件上,所以在创建虚拟装置时,需要在创建过程中一步一步优化和缩减大小。物理装置开发商喜欢安装一个“胖”操作系统,因为他们往往有一个很充足的存储空间,但是虚拟装置则不同,它们必须变小,以便能够在网络上上传和下载。 在这里,“够用就好”(Just enough OS)是虚拟装置中操作系统定制的基本出发点。“够用就好”的思想最早来源于模块化的操作系统如Linux,但是,目前也有工具可以把微软的操作系统修剪到一个Just enough OS。一个比较极端的例子是BEA的 Liquid VM,BEA公司的虚拟装置把BEA J-Rockit Java虚拟机部署在一个很“薄”的层上,该层把Java虚拟机产生的低级系统调用直接翻译成VMware虚拟机可以执行的指令。这样一来,Java虚拟机不再像在以往的操作系统上受到重重限制了。 虚拟装置不需要的服务和端口必须剔除和关闭。比如,如果虚拟装置不需要向文件系统中写入数据,那么有必要关闭FTP服务和相应端口。当然,你还是需要打开Web端口,以便虚拟装置的用户通过Web的方式来修改虚拟装置的一些配置信息。 (二)初始化设置 一旦虚拟装置安装上以后,用户应该尽量不去修改它的配置。于是,初始化设置变得非常重要,而且开发人员必须能够让用户在初始化的时候设置某些配置,比如设置虚拟装置的IP或者虚拟装置支持DHCP,并且在配置时给出Web管理界面的URL(http/https + IP 地址 + 端口)。 有了Web控制台或者命令行控制台后,用户就可以执行一部分对虚拟装置的管理操作了。对于开发人员来说,初始化虚拟装置时,需要支持以下配置:建立用户名和密码,以及管理员用户(虚拟装置的管理员,并非操作系统的管理员),设定网络配置信息,使用DHCP或者使用静态IP并且为虚拟装置设定主机名,设定SNMP配置信息,设定虚拟装置上各种服务的日志级别以及日志rotation策略,生成一个用于生成SSL证书的SSL 证书请求,上传一个SSL 证书来保证虚拟装置的通信安全,同步系统日期时间,出厂设置等。 (三)添加“标准”组件 虽然不同的虚拟装置可能会需要不同的组件,但是以下组件基本上是每个虚拟装置都需要的。这些“标准”组件以后可能会被写作一个“虚拟装置框架”中,方便开发人员建立虚拟装置,这些组件有: 1(一个“够用就好”的操作系统 同“(一)优化操作系统”所述的“够用就好”(Just enough)的操作系统。此处不再赘述。 2(命令行控制台 最好提供一个单独开发的命令行界面,可以自己制定一些参数或者语法。它的基本功能有:设置/显示网络配置,设置SSL,监控进程,管理用户,生命周期管理。 3(Web管理控制台 即使开发人员提供了功能强大的命令行控制台来管理虚拟装置,但是用户更倾向使用图形化的Web控制台。Web控制台需要具备的基本功能有:包括命令行控制台的主要功能、日志管理、NTP(网络时间服务)。此外还有解决方案配置信息:虚拟装置提供某类解决方案,会涉及到一些自定义的控制选项,使用Web控制台的方式让用户填写这些信息,可以使配置流程更加清晰。 (四)虚拟机设置 一个虚拟装置是创建在一个虚拟机内部的,于是根据虚拟装置上的具体应用来配置虚拟机也是一个必要步骤。由于大部分虚拟装置提供的是服务器端服务,所以很多虚拟硬件是不会使用到的,比如软盘、CD、USB等等,所以最好将这些虚拟硬件移出虚拟机。 (五)打包和发布 当创建完成一个虚拟装置并且测试通过后,就可以将它打包供用户下载了。先准备一个空文件夹,将虚拟机的虚拟硬盘和 配置文件,以及readme等说明文件放入,压缩成zip或者tar文件即可。 至此,经过“优化操作系统”,“初始化设置”,“添加’标准’组件”,“虚拟机设置”,“打包和发布”一系列步骤,一个虚拟装置被创建并可以被用户下载使用了。 3.6.15 小结 本节阐述了虚拟化涉及到的操作系统适配技术,这类技术旨在修改客户操作系统使其更适合在虚拟化环境中运行,其研究方向主要有三个:1) 修改操作系统使其能够迁入虚拟化环境中,并且根据具体环境的特点,通过不同的方式提高虚拟机的性能;2) 使虚拟机能够实行自行管理,或者在虚拟机监控管理时,能够从客户操作系统内部获得支持;3) 为特殊的应用场景定制操作系统,使得操作系统不再是面向所有的应用程序,而是将操作系统与应用程序紧密联系在一起,让操作系统成为只是支持单一应用程序的个性化系统服务。除这三个主要方向外,为了提高应用的易用性和可靠性而兴起的虚拟装置技术,也是一种由虚拟化产生的操作系统适配技术。 操作系统适配技术是各种虚拟化方案都会涉及到的一类重要技术,当将硬件平台、虚拟机管理器、操作系统适配及标准化体系等有机地融合在一起,才能为用户提供具有良好可扩展性和易维护性、具有良好整体性能的虚拟计算机系统。
/
本文档为【计算系统虚拟化】,请使用软件OFFICE或WPS软件打开。作品中的文字与图均可以修改和编辑, 图片更改请在作品中右键图片并更换,文字修改请直接点击文字进行修改,也可以新增和删除文档中的内容。
[版权声明] 本站所有资料为用户分享产生,若发现您的权利被侵害,请联系客服邮件isharekefu@iask.cn,我们尽快处理。 本作品所展示的图片、画像、字体、音乐的版权可能需版权方额外授权,请谨慎使用。 网站提供的党政主题相关内容(国旗、国徽、党徽..)目的在于配合国家政策宣传,仅限个人学习分享使用,禁止用于任何广告和商用目的。

历史搜索

    清空历史搜索