80x86机器的虚拟化最近太火了,不但微软加入了战团,还有一堆Startup摇旗呐喊。那到底哪种虚拟机好呢?本文就尝试接着笔者的一些经验,做一些个人总结。
好是一个相对的概念。市面上的虚拟机不但表面上产自不同的公司,其核心实现技术也五花八门,适用的场合也千差万别。一方面你要知道虚拟化技术能给你带来什么,一方面你要知道你自己需要什么, 一方面还要知道要达到你的目标选用什么虚拟机,用什么虚拟化战略最适合你。这个过程就是选型的过程。希望读完本文之后,你对80x86的虚拟化技术和其发展现状能够有一个大概的了解。略去虚谈虚拟化技术的好处的文字,让我们直接来看虚拟机是怎么实现的,从而给市面上的虚拟机做一个分类。
如果我们重新实现一个虚拟机,有好几种选择。最直接的选择是用软件来模拟硬件。写一个简单的while循环就可以模拟一个cpu的工作了:
while (true) {
var instr = GetNextInstruction();
switch (instr) {
case xxx:
// do xxx
case HALT:
return;
}
}
这也是普通的游戏机模拟器的实现原理。再加上软件模拟的外设,比如主板,硬盘什么的。这类虚拟机叫Enumlator。
Emulator有一个最大的优势是独立于底层硬件。你可以在586上模拟出6502CPU来。这对于开发特殊硬件的软件的工程师特别有用。而由于模拟器的效率低下,最终也只能沦落为调试工具。为了改进性能,人们引入了编译来代替解释执行。著名的JIT(JVM也算是虚拟机啊)就是其中的一种,QEMU则是80x86领域的字节码编译的虚拟机实现。但是这更多地是一种运行时的优化技术,并没有根本改变其实现,也没有根本地改变执行效率。
根本地解决方案是,不用软件的循环去模拟CPU,而是直接使用宿主机的CPU来执行。而且内存也不用去模拟,也可以直接用宿主机的CPU来执行。这就是Virtualization技术。
内存是比较容易实现的,一般都是有一个映射表来做虚拟内存和实际内存地址的映射。这种内存虚拟化已经是广泛使用并且非常成熟的技术。AMD后来提出的虚拟化技术进一步把这种表映射在硬件层面上提供了加速。
问题的难点在于80x86的ring结构上。ring0到ring3,权限依次递减。实际使用中,Windows只利用了ring 0和ring 3两个级别。Guest OS需要运行在80x86的Ring 0级别上。但是Host OS自己已经是在80x86的Ring 0级别上了。虚拟机作为一个用户态的应用程序,只有ring3的特权,这个状态的CPU是不能满足Guest OS的需要的。这也是为什么80x86虚拟化技术难以实现的原因。所以,在最开始的时候,为了达到虚拟化的目的,Guest操作系统必须经过修改。最开始的时候Xen就是这么实现的,需要Guest OS是打过补丁之后的特定版本的Linux。显而易见,Windows的内核是无法被打补丁的。所以,Para-Virtualization只适合开放源代码或者厂商支持的操作系统。
但是随着硬件的进步。Intel提出了Vt-d技术,Amd提出了Pacifica技术。虽然名称不同,但是结果都是让ring0之上再多出了一层。从而使得虚拟机可以欺骗过Guest操作系统,让它认为自己就是运行在普通的CPU之上。所以Full-Virtualization就出现了。为了利用这些CPU的新技术,它们都有一个直接贴近硬件的驱动程序,并不是完全基于Host OS之上的。
人类的追求是无止尽的。在把全虚拟化的虚拟机用在实战中,特别是高负载的服务器场合之后,很快性能问题就暴露出来。CPU速度是没有问题的,非常快。问题集中在内存消耗和I/O操作速度与随之而来的CPU占用率的问题。
当一台机器能够安装多个虚拟机之后,人们就想装尽可能多的虚拟机,从而提高整体的资源利用率。但是由于内存的限制,使得这个单机负载的虚拟机数量很难提高,同时内存的利用率却并不高。假设每个虚拟机都分配了1G内存,内存利用率是60%,那就每台有400M的内存空闲。一台4G的机器装了4个虚拟机,就有1.6G的空闲内存。所以装5台虚拟机是一点问题都没有的。但是由于每个虚拟机都自己捏了一把富余的内存在手上以防万一,导致整体的利用率上不来。为了解决这个问题,大厂的虚拟机都有很多优化,比如Deflate,Ballooning之类的。而这些优化往往是在Guest操作系统上装一些特殊的驱动程序去控制Guest操作系统的内存分配(或者是Linux内核的直接支持)。
I/O速度和CPU占用率的问题是由软件模拟的外设,特别是硬盘和网卡照成的。解决方案自然也是尽可能的利用真实的硬件。通过给Guest OS上装优化的驱动程序就可以实现。不过要进一步提高性能,就卡在了DMA(Direct Memory Access,直接内存访问)技术上。DMA是一个I/O优化技术,它可以让CPU不参与I/O,而外设直接访问内存。由于内存地址是虚拟化的,而DMA是硬件控制的,又无法被修改从而知道虚拟化之后的地址。这个问题的解决,仍然依赖于Intel、AMD。相信将来会有支持硬件支持的虚拟I/O的CPU上市。不过从计划发布,到现在我们已经等了很久了。
这个时候,由于效率的原因Full-Virtualization又变成Para-Virtualization了。因为Driver也是对Guest OS的一种修改,不再是透明地虚拟化了。如果对应操作系统没有驱动,你就没法用(或者说没法利用优化之后的外设和内存)。而这个对于Windows来说,又是一个问题了。KVM至今都没有发布Windows的硬盘Virtio驱动,导致效率低下。
今天讲的是硬件流派,明天继续讲软件流派。未完待续……