虚拟化技术的应用十分广泛. 当前虚拟化技术主要关注于服务器的虚拟化, 或在单个主机上寄存多个独立的操作系统. 本文首先介绍虚拟化技术的原理, 然后讨论多个虚拟化技术的实现方法. 另外介绍了一些其它的虚拟化技术, 比如Linux上操作系统级的虚拟化技术.
虚拟化把事物从一种形式改变为另一种形式. 计算机的虚拟化使单个计算机看起来像多个计算机或完全不同的计算机.
虚拟化技术也可以使多台计算机看起来像一台计算机. 这叫做服务器聚合(server aggregation)或网格计算(grid computing).
首先我们回顾一下虚拟化技术的历史.
虚拟化技术的历史
虚拟化技术不是一个新的主题; 实际上, 它已有40年的历史. 最早使用虚拟化技术的是IBM 7044计算机, 它是基于MIT(麻省理工学院)为IBM704计算机开发的分时系统CTSS(Compatible Time Sharing System), 和曼彻斯特大学的Atlas项目(世界最早的超级计算机之一), 首次使用了请求调页和系统管理程序调用.
硬件虚拟化
IBM早在1960年就认识到虚拟化技术的重要性, 于是开发了型号为Model 67的System/360主机. Model 67主机通过虚拟机监视器(VMM, Virtual Machine Monitor)虚拟所有的硬件接口. 在早期的计算中, 操作系统被称做Supervisor. 能够运行在其它操作系统之上的操作系统被称做hypervisor(名称首次出现在1970年).
VMM直接运行在底层硬件上, 允许执行多个虚拟机(VMs). 每一个VM(虚拟机)运行自己的操作系统实例 -- 早期时候称为CMS, 或会话监视系统(CMS, Conversational Monitor System). 然后VM继续发展. 今天你能够在System z9主机上发现VM, 它能够向后兼容, 甚至是System/360.
处理器虚拟化
另外一个早期使用的虚拟化技术, 仿真处理器, 也叫做P-code(or pseudo-code)机. P-code是一种机器语言, 运行在虚拟机上而不是实际的硬件. 知名的P-code语言在1970年由加州大学圣地亚哥分校的Pascal系统项目组开发. 它可以把Pascal程序编译成P-code代码, 然后在具有P-code功能的虚拟机上运行. P-code程序具有高度可移植性, 能够运行在任何具有P-code功能的虚拟机上.
1960年的BCPL语言(基本组合程序设计语言, Basic Combined Programming Language)也使用了同样的概念, 它是C语言的前身. 编译器首先把BCPL代码编译成一个中间机器代码: O-code. 然后, O-code被编译成目标机器代码. P-code模型已被广泛使用到各种编译器当中, 从而为编译器移植到新的主机架构提供了复杂性.(通过一个中间语言分成前端和后端).
Java虚拟机(JVM)
Java虚拟机也采用了P-code模型. 从而我们可以简单通过移植JVM程序到新架构的机器上来广泛发布Java程序.
指令虚拟化
近来频繁出现的虚拟化概念: 指令虚拟化, 也叫做二进制翻译. 在这个模型中, 虚拟指令被动态翻译成底层硬件的物理指令. 程序执行后, 代码一段一段地被翻译. 如果出现分支, 一套新的代码指令将被引入和翻译. 这十分类似于缓存操作, 指令块从内存移动到本地的快速缓存内存中执行.
近来Transmeta公司设计的Crusoe中央处理器使用了该模型. 二进制翻译由Code Morphing专利技术实现. 类似的一个实例, 全虚拟技术通过使用动态生成代码扫描来发现和重定向特权指令(解决特殊处理指令集中的问题).
虚拟化技术的类型
现在不只存在一种虚拟化技术. 事实上有多种方法可以使用不同层次的抽象来实现同样的结果. 本章介绍Linux上三种最常用虚拟化技术的优点和弱点. 业届有时使用不同的术语来描述同一个虚拟化技术. 为了保持连续性, 下面使用的术语参考了其它的术语.
虚拟化技术和游戏
一篇虚拟化技术的文章如果没有提到复合式大型电玩模拟器(MAME)就不是一篇完整的文章. MAME, 就如名字一样, 是一个能够模拟以往arcade游戏的机器模拟器(全部). 做一个补充, 整个机器是被虚拟的, 包括声音和图形还有控制硬件. MAME是一个非常棒的应用程序, 你也可以通过仔细阅读源码来了解它是如何实现的.
硬件模拟器
无可否认, 最复杂的虚拟化技术是硬件模拟器. 在这个方法中, 首先在主机系统上创建硬件VM, 然后模拟硬件的功能, 如图1显示:
图1. 硬件模拟器: 使用VM模拟需要的硬件
正如你可能猜到, 硬件模拟器的主要问题是速度极慢. 因为每一个指令在底层硬件都需模拟, 所以速度慢了100倍. 高保真模拟还包含了循环校验, 用于模拟CPU的管道和缓存行为, 实际速度会慢了1000倍.
硬件模拟有自己的优点. 比如, 使用硬件模拟, 你能够在基于ARM处理器的主机上模拟运行基于PowerPC未经任何修改的操作系统. 你甚至能在每个不同模拟处理器上运行多个虚拟机.
模拟器和开发
硬件模拟器最有意思的一个应用是firmware(固件)和硬件协作开发. firmware开发人员无需等待最新硬件的推出, 他们可以使用目标硬件的虚拟机来验证实际代码中的许多概念.
全虚拟化
全虚拟化(Full virtualization), 也称为原始虚拟化技术, 是另一种虚拟化方法. 该模型使用虚拟机协调客户操作系统和原始硬件(见图2). 这里"协调"是一个关键词, 因为VMM在客户操作系统和裸硬件之间用于工作协调. 一些受保护的指令必须由Hypervisor(虚拟机管理程序)来捕获和处理. 因为操作系统是通过Hypervisor来分享底层硬件.
图2. 全虚拟化: 使用Hypervisor分享底层硬件
全虚拟化的运行速度要快于硬件模拟, 但是性能方面不如裸机, 因为Hypervisor需要占用一些资源. 全虚拟化最大的优点是操作系统没有经过任何修改. 它的唯一限制是操作系统必须能够支持底层硬件(比如, PowerPC).
老机器上的Hypervisors
一些老的硬件如x86, 全虚拟化遇到了问题. 比如, 一些敏感的指令需要由VMM来处理(VMM不能设置陷阱). 因此, Hypervisors必须动态扫描和捕获特权代码来处理问题.
半虚拟化
半虚拟化(Paravirtualization)是另一种类似于全虚拟化的热门技术. 它使用Hypervisor(虚拟机管理程序)分享存取底层的硬件, 但是它的客户操作系统集成了虚拟化方面的代码. 该方法无需重新编译或引起陷阱, 因为操作系统自身能够与虚拟进程进行很好的协作.
图3. 半虚拟化: 通过客户操作系统分享进程
上面提到过, 半虚拟化需要客户操作系统做一些修改(配合Hypervisor), 这是一个不足之处. 但是半虚拟化提供了与原始系统相近的性能. 与全虚拟化一样, 半虚拟化可以同时能支持多个不同的操作系统.
操作系统级的虚拟化
最后一个我们需要了解的虚拟化技术是操作系统级的虚拟化(Operating system-level virtualization), 它使用不同于上面的虚拟化方法. 该技术在操作系统之上虚拟多个服务器, 支持在单个操作系统上简单隔离每一个虚拟服务器(见图4).
图4. 操作系统级的虚拟化: 隔离单个服务器
操作系统级的虚拟化需要修改操作系统内核, 它的优点是具有原始主机的性能.
为什么虚拟技术如此重要?
在了解当今主流的linux虚拟化技术之前, 我们先来看虚拟化技术的优点.
从商业角度来看, 使用虚拟化技术有非常多的原因. 不过大多是用于服务器加固. 简单来说, 如果你能够在单个服务上虚拟多个系统, 这样少数的几台计算机显然能够节省耗电, 空间, 冷却和管理开支. 考虑到确定服务器利用状况的困难, 虚拟化技术支持动态迁移(Live Migration). 动态迁移允许操作系统能够迁移到另一台全新的服务器上, 从而减少当前主机的负载.
虚拟化技术对开发人员来说也非常重要. Linux内核占用了一个单一的地址空间, 这意味内核或任何驱动程序错误都能导致整个操作系统停止工作. 而通过虚拟化你可以运行多个操作系统, 如果其中一个系统由于错误而宕机, Hypervisor和其它的操作系统不会受到任何影响. 这对调试内核来说就如同调试用户空间程序一样.
Linux相关的虚拟化项目
表1显示了几个可能加入到Linux(内核)的虚拟化技术, 主要关注于开源.
表1. Linux相关的虚拟化项目
Bochs 模拟器 LGPL
QEMU 模拟器 LGPL/GPL
VMware 全虚拟化 闭源
z/VM 全虚拟化 闭源
Xen 半虚拟化 GPL
UML 半虚拟化 GPL
Linux-VServer 操作系统级虚拟化 GPL
OpenVZ 操作系统级虚拟化 GPL
更多其它的虚拟化技术, 请查阅参考资料栏目.
Bochs(模拟器)
Bochs是一个仿真x86 CPU的计算机模拟器, 它具有可移植性和可运行在多种平台上, 如x86, PowerPC, Alpha, SPARC和MIPS. Bochs的优点是不仅能模拟处理器, 而且能模拟整台计算机, 包括外设如键盘, 鼠标, 视屏图像硬件, 网卡等.
Bochs能被配置成一台老的Intel 386计算机, 或更新的处理器如486, Pentium, Pentium Pro, 或64位处理器. 甚至能模拟图形指令如MMX和3DNow.
你也能够通过Bochs模拟器在Linux系统上运行任何Linux发行版, 还有Microsoft® Windows® 95/98/NT/2000(和多种应用程序), 甚至是BSD操作系统(FreeBSD, OpenBSD,等).
库级的虚拟化
这里没有讨论另一个虚拟化技术, 它通过库来模拟操作系统的一部分. 比如Wine(一部分为linux开发的win32 API)和LxRun(一部分为Solaris开发的Linux API).
QEMU(模拟器)
QEMU是另一个类似于Bochs的模拟器, 它有一些值得注意的地方. QEMU支持2个操作模式. 一个是全系统模拟模式. 该模式类似Bochs模拟整个计算机系统(包括处理器和外设). 而且能在合理的速度下使用动态翻译模拟一些处理器架构如X86, X86_64, ARM, SPARC, PowerPC和MIPS. 你还可以在Linux, Solaris和FreeBSD系统上模拟Windows系统(包括XP)和Linux系统. QEMU支持其它的操作系统组合(更多信息见参考资料栏目).
QEMU的第二个模式: 用户模式模拟. 该模式能寄存在Linux上, 不同平台的二进制程序也能运行. 比如, 一个MIPS平台上的二进制程序能够运行在x86平台上的Linux系统. 其它支持的平台包括ARM, SPARC和PowerPC, 而且还有更多正在开发的平台.
VMware(全虚拟化)
VMware是一个商业级的全虚拟化技术. Hypervisor是客户操作系统和硬件之间的抽象层. 该抽象层允许任何其它客户操作系统运行在主机操作系统之上.
VMware也能虚拟I/O硬件, 增加了高性能设备驱动到Hypervisor中.
整个虚拟(机)环境实际上是一个单独的文件, 这意味整个系统(包括客户操作系统, 虚拟机和虚拟硬件)可以简单快速地整合到一个新的主机, 从而实现负载均衡.
z/VM(全虚拟化)
当IBM System z™是一个全新名称的时候, 事实上可以追述到1960年. System/360在1965年使用虚拟机方法实现了虚拟技术. 令人感兴趣的是System z能够与最老的System/360系列主机兼容.
z/VM®是System z操作系统的Hypervisor. 核心程序是控制程序(CP), 向客户机操作系统提供硬件资源虚拟, 包括Linux(见图5). 允许在多个客户操作系统上虚拟多个处理器和其它资源.
图5. 使用z/VM的操作系统级虚拟化技术
z/VM可以为那些需要相互通讯的客户操作系统虚拟一个客户局域网(LAN). 整个客户局域网位于Hypervisor中, 所以很安全.
Xen(半虚拟化)
Xen由XenSource开发, 一个开源免费的操作系统级准虚拟技术. 回顾一下半虚拟技术, Hypervisor和操作系统共同协作, 虽然操作系统需要做一些修改, 但是性能上比较接近于原始性能.
Xen需要与系统共同协作(客户操作系统需要修改), 只有打过补丁的系统才能使用Xen. 从Linux角度来看, Linux本身是开源的, 结果是Xen的性能要好于全虚拟化技术. 但是从系统支持(比如支持其它非开源的操作系统)的角度来看, 这显然是一个不足之处.
在Xen上可以运行Windows客户机, 但需要Intel Vanderpool或AMD Pacifica处理器的支持. 其它支持的操作系统包括Minix, Plan 9, NetBSD, FreeBSD, 和OpenSolaris.
用户模式Linux(半虚拟化)
用户模式Linux(UML, User-Mode Linux)支持在linux系统的用户空间运行其它Linux操作系统. 每一个客户操作系统是主机Linux系统上的一个标准的进程(见图6). UML允许多个Linux内核(有自己的用户空间)运行在单个Linux内核之中.
图6. 用户模式Linux: Linux寄存
在Linux 2.6内核中, UML存在于主内核树中, 但是必须打开和重新编译才能使用UML. 一些修改包括, 设备虚拟, 允许客户操作系统分享存在的物理设备, 比如块设备(磁盘, CD-ROM, 和文件系统), 控制台, 网卡, 声卡等.
注: 客户操作系统内核运行在用户空间模式, 内核必须专门编译才能在客户系统中使用(可与主机操作系统内核版本不同). 整个主机存在两套内核, 一个是主机内核(直接位于物理硬件之上), 另一个是客户内核(运行在主机内核的用户空间之中). 这些内核甚至可以相互嵌套, 允许客户机内核运行在另外一个客户机内核之中.
Linux-VServer(操作系统级虚拟化)
Linux-VServer是操作系统级的虚拟化解决方案. Linux-VServer虚拟Linux内核, 可以有多个用户空间环境, 也称做虚拟专用服务器(VPS), 各个VPS各自独立运行. Linux-VServer是通过修改Linux内核来隔离用户空间.
为了隔离每个单独的用户空间, 我们先了解上下文环境. 上下文是一个VPS进程的容器, 因此我们可以使用ps等工具来了解vps进程的状况. 系统首次初始化后, 内核定义了一个缺省的上下文, 管理端能够查看所有的上下文(所有正在执行的进程). 你会猜到, 内核和内部数据结构需做一些修改来支持虚拟化.
Linux-VServer使用chroot隔离每个VPS的root目录. 我们知道chroot允许指定新的root目录, 但需额外的功能(叫做chroot-Barrier)来限制VPS不会跨越到上级目录. 在设定一个隔离的root目录后, 每一个VPS有自己的用户列表和root口令.
Linux 2.4和2.6内核支持Linux-VServer, 可运行在许多平台上, 包括x86, x86-64, SPARC, MIPS, ARM和PowerPC.
OpenVZ(操作系统级虚拟化)
OpenVZ是一个类似于Linux-VServer的操作系级级虚拟化解决方案. 它有一些自己独特的地方. OpenVZ是一个内嵌虚拟化的内核(修改过的), 它支持用户空间隔离, 虚拟专用主机(VPS)和一套用户管理工具. 比如, 你可以通过下面命令简单创建一个新的VPS:
列表1. 从命令行创建一个VPS
$ vzctl create 42 --ostemplate fedora-core-4
Creating VPS private area 正在创建VPS专用区域
VPS private area was created VPS专用区域成功创建
$ vzctl start 42
Starting VPS ... 启动VPS
VPS is mounted 加载VPS分区
你也可以使用vzlist命令列出所有已创建的VPS, 这有点类似于标准的Linux命令ps(查看进程的状态).
OpenVZ包含一个两级的CPU调度器来调度进程. 首先, 调度器确定需要使用CPU的VPS. 然后第二级调度器根据进程的优先级来执行vps进程.
OpenVZ支持beancounters. 一个beancounters包含了定义vps资源属性的许多参数. 这为vps提供了控制, 定义多少可有内存, 多少可用IPC资源, 等.
OpenVZ独特的地方是能够设置检查点和vps迁移(从一台服务器迁移到另一台服务器). 检查点能够停止正在运行vps并保存当前状态到一个文件. 该文件在迁移过程中可用于在新服务器上恢复运行VPS.
OpenVZ支持许多硬件结构, 包括x86, x86-64, 和PowerPC.
全虚拟化和半虚拟化的硬件支持
回顾一下IA-32(x86)体系结构上存在的一些问题. 某个特权指令不能够引起陷阱, 可基于模式返回不同结果. 比如, x86的STR指令可以获取安全状态, 但返回值是基于特别请求者的权限级别. 当试图在不同级别虚拟不同操作系统的时候是一个问题. 比如, x86支持4环保护, 0级(最高权限)通常运行操作系统, 1和2级支持操作系统服务, 3级(最低级别)支持应用程序. 不过硬件厂商已经认识到这些问题(和其它的问题), 而且开发了新的设计来支持和加速虚拟化技术.
Intel正在开发新的虚拟技术, 能在x86(VT-x)和Itanium(VT-i)结构上支持Hypervisors. VT-x支持两个新的操作. 一个是VMM(root), 另一个是客户操作系统(非root). root方式具有最高权限, 而非root方式是非特权的(甚至ring 0). 结构方面也支持自定义指令(使用vmm)终止VM(客户操作系统)和保存处理器状态. 其它功能请查阅参考资源栏目.
AMD也正在开发硬件级的虚拟化技术, 代号为Pacifica. Pacifica维护了一个客户操作系统的控制块(通过特殊指令保存执行状态). VMRUN指令允许虚拟机(和它相联系的客户操作系统)运行直到VMM重新获得控制权(可自定义). 可配置性允许VMM为每一个客户机自定义权限. Pacifica也能使用主机和客户机内存管理单元(MMU)表来提高地址翻译.
这些硬件虚拟化技术能够应用到许多的虚拟化技术当中, 包括Xen, VMware, User-mode Linux, 和其它的.
Linux KVM(内核虚拟机)
最近的Linux新闻经常报道Linux 2.6.20内核增加了KVM虚拟化技术. KVM是全虚拟化的解决方案, 它的特点是系统内核通过添加内核模块使内核自身成为一个Hypervisor(虚拟机管理程序). 内核中的KVM模块通过/dev/kvm字符串设备显示被虚拟的硬件. KVM使用修改过的QEMU进程做为客户操作系统接口.
图7. KVM的虚拟化
KVM模块向内核增加了一个新的执行模式: 客户模式. 官方原始内核(vanilla kernel)支持内核和用户模式. 客户模式用于执行所有非I/O客户代码, 普通用户模式支持客户I/O.
增加KVM到Linux内核是Linux发展的一个重要里程碑, 这也是第一个整合到Linux主线内核的虚拟化技术. KVM将包含于2.6.20内核数中, 现在你也可以通过内核模块方式在2.6.19内核使用kvm. 当运行在支持的硬件(需Intel VT和AMD SVM处理器)上, kvm支持Linux(32和64为)和Windows(32为)客户机. 更多KVM信息, 请查阅参考资源栏目
总结
虚拟化技术是一个新的而且重要的领域, 如果"新"包括了过去的40年. 在过去它已经使用于许多场合, 但是现在最主要的一个焦点是服务器和操作系统的虚拟化. 比如像Linux, 虚拟化给性能, 可移植性和复杂性提供了许多选项. 这也意味者你能够为你的应用程序和项目选择最合适的虚拟化方法.
参考资源
学习
您可以参阅本文在 developerWorks 全球站点上的 英文原文 。
如果你不熟悉IBM系统, New to IBM Systems页面提供了大量有关System i, p, x, z,等的详细信息.
IBM的网格计算基于一套开放的标准和协议, 通过虚拟分布式的计算机来创建一个单一强大的系统.
在 developerWorks Linux 专区 中可以找到为 Linux 开发人员准备的更多资源.
随时关注 developerWorks 技术事件和网络广播.
获得产品和技术
Bochs和QEMU是PC模拟器, 允许如Windows或Linux运行在linux操作系统的用户空间.
VMware是一个流行的全虚拟化解决方案, 能够虚拟无需修改的操作系统.
z/VM是一个最新的基于64位z/架构的虚拟机操作系统. z/VM提供全虚拟化和支持大多的操作系统, 包括Linux.
Xen是一个开源的半虚拟化解决方案, 需修改客户机的操作系统, 通过与hypervisor的协作能获得接近于原始系统的性能.
User-mode Linux是另外一个开源的半虚拟化解决方案. 每一个客户操作系统是主机操作系统的一个标准进程.
coLinux, 或协作Linux, 是一个提供两个操作系统共同分享底层硬件的虚拟化解决方案.
Linux-Vserver是一个linux上的操作系统级的虚拟解决方案, 每一个客户服务器都被安全的隔离开来.
OpenVZ是一个操作系统级的虚拟化解决方案, 支持检查点和动态迁移.
Linux KVM是第一个整合到Linux主线内核的虚拟化技术. Linux内核在载入一个内核可加载模块(kvm)后, 内核自身成为了一个Hypervisor程序, 如果有合适的硬件支持(Intel VT或AMD SVM处理器), 系统可运行未修改过的linux和windows客户机操作系统.