虚拟机是怎么实现的?

原文转自:http://www.manio.org/cn/virtual-machine-implementation/缓存

997年,斯坦福的Mendel Rosenblum带着Edouard Bugnion, Scott Devine在SOSP上发了篇论文,叫作Disco: running commodity operating systems on scalable multiprocessors (http://research.cs.wisc.edu/areas/os/Qual/papers/disco.pdf)。发了以后,我想他们应该是以为这个主意太好了,就开了家公司,名叫VMWare。

这篇论文起名叫Disco(迪士高)是由于虚拟机自己不是一个新的东西,大概在上世纪70年代就有了。做者们为了表示敬意,或者是显示这是一个复古的东西,就把这个项目取名为disco。这篇论文介绍了虚拟机关键技术,用来回答这个问题再合适不过了。(多年以后,OSDI上的另外一篇论文(Memory Resource Management in VMware ESX Server)介绍了一些VMWare的改进。近年来论文愈来愈多。)

当初他们为何要作虚拟机?简单说就是,新硬件层出不穷,可是OS赶不上。当初,他们想在Stanford的ccNUMA机器上跑IRIX(一个操做系统)。但是IRIX跑不起来。他们以为修改OS或者写一个新的OS太难了(由于一个操做系统从出生到成熟要很长的时间,无数BUG要FIX,无数的新功能要增长。。。那样人家博士要怎么毕业。。)。因此,他们决定用虚拟机。

对于他们的项目,虚拟机大体有下面这些好处:网络

  1. 只要对商业OS作简单地修改,就能让他们在多个VM(Virtual Machine)间共享内存。
  2. Flexible。除了论文里的IRIX,实际上其余的OS也能跑。
  3. 扩展性好。系统能够以虚拟机为单位扩展。
  4. fault-containment。每个VM都是一个几乎独立的个体,一个坏了,不影响另外一个。
  5. 新老软件可共存。好比,新的软件只能在Linux-3.15跑。你能够用两个VM,一个是Linux2.6,一个是Linux-3.15。

这篇文章回答下面这几个实现虚拟技术的关键问题:ide

  1. VMM(Virtual Machine Monitor, 或者叫hypervisor)是怎么管住Guest OS的?或者说,皇上(VMM)是怎么防止大臣(OS)夺权的?
  2. 有那么多个操做系统一块儿运行,内存是怎么管理的?
  3. 多个VM之间是怎么分享资源的?或者说,1GB内存怎么当2GB用?

注意:如无特别说明,这篇文章里所说的处理器是指MIPS,而不是x86。函数

VMM(Virtual Machine Monitor, 或者叫hypervisor)是怎么管住Guest OS的?或者说,皇上(VMM)是怎么防止大臣(OS)夺权的?

new1


要理解VMM是怎么工做的,咱们得先了解没有VMM的时候,系统是怎么工做的。在没有VMM的时候,计算机系统中的”应用”可分为用户进程(好比VIM)和操做系统。他们分别运行在不一样的模式中(mode)。咱们用一个类比来解释系统中的模式(mode)。模式这个机制是用来限制一段指令所在的环境的权限的,它是须要处理器的支持的。MIPS结构当时有三个模式:用户模式(user mode),长官模式(supervisor mode,原谅个人翻译…)和内核模式(kernel mode)。这三种模式分别对应于人类社会里的民宅、官衙和金銮殿。显而易见,在金銮殿里的人拥有的权限最高,民宅里的最低。咱们能够说,在没有VMM时,用户进程住在民宅里,县衙空着,OS住在金銮殿里(如图)。用户能够直接作一些不用什么特权的事情(unprivileged instructions),好比计算1+1。作这些事情不通过OS。可是,有些要特权才能作的事情,必定要通过OS。好比保存正在编辑的文档到硬盘(IO operations)。访问硬盘是特权操做是由于硬盘是共享的资源,要有人管着,不能让人乱来。试想,要是人人都能读写档案馆的档案,那不就乱套了。

new2
VIM(用户进程)不能直接写磁盘上的文件。VIM必须请求在金銮殿里的操做系统来作。怎么请求呢?经过系统调用(system call)。系统调用的过程是这样的:好比要调用的是write(fd, buf, len, off),首先把fd, buf, len, off放到stack里,而后再把一个write()函数对应的号码(system call number)放到stack里,最后调用一个特殊的指令使CPU进入内核模式(图中的圈1)。在x86结构中,这个指令是int(中断)。在MIPS结构中,这个指令是trap。这个指令会引导CPU执行一段代码(trap handler),依照stack里的system call number 找到对应的函数(在这里是write()的实现),而后调用这个函数(函数的参数在刚才的stack里)。在这里函数里,操做系统调用文件所在的文件系统里的write()实现,文件系统使用磁盘的驱动来最终实现。因此文件的操做完成后,操做系统调用与trap功能相反的一个指令,回到VIM程序的指令里(图中的圈2)。操作系统

关于trap(陷阱)指令:把这个指令叫trap(陷阱)是很是形象又准确的。当trap指令执行里,就像是掉入了有更多特权的人(好比皇上)设置的陷阱里同样,任人摆布。scala


new3
操做系统维护本身的特权的过程大概就是这样。可是这个特权等级究竟是怎么实现的呢?咱们能够想像CPU里有一个特权状态(privileged state bit)。状态为开(On)的时候,CPU的特权等级高,你能够作任何事,包括转到低特权状态。关(Off)的时候,你所能作的事情就所限了。那怎么从off状态转到on状态呢?你必须到执行CPU的特殊指令,这个指令会把你带到一个特定的地方执行操做系统的指令,检查你是否是有进入高特权状态的权限。这就像是在机场,你能够很容易地从登机口到售票大厅,但是你要从售票大厅到登机口,你就得过安检。另外,为何操做系统就能有高特权呢?Hmm…由于操做系统一开始就把那占了,以后运行的应用程序就只能听它使唤了。

如今,终于要说VMM(virtual machine monitor, 或者叫hypervisor)是怎么实现的了。以下图:
new4
如今VMM进了金銮殿,有了最高的特权。操做系统被放到了官衙里(可是它本身并不知道)。用户进程仍是在民宅里住着。要是如今用户进程VIM调用write(),会发生什么?在这种状况下,用户进程会trap到VMM(拥有kernel mode)里去。可是,VMM并不知道如何处理write()。因此,VMM接下来会调用操做系统的里对应的trap handler,这个handler会执行文件系统的write()。 在执行过程当中,文件系统的非特权指令能够直接在真的CPU上执行。要是文件系统运行特权指令,CPU会从操做系统(supervisor mode)trap到VMM(kernel mode)里去,由VMM仿真(emulate)操做系统要运行特权指令。之因此要由VMM来仿真,有几个理由。第一,VMM不相信操做系统。例如,在VMM上可能同时运行着几个操做系统,若是让其中一个操做系统执行直接内存访问的指令,它可能修改内存中另外一个操做系统的代码或数据。第二,操做系统只了解虚拟的环境,并不知道实际的环境。例如,操做系统想要写/dev/sda3的第10个sector。可是,实际上/dev/sda3可能对应的是VMM里一个叫/fake_dev/sda3.data的文件。这个时候,咱们就须要VMM来把操做系统的指令转化为实际环境中的操做了。翻译

仿真完特权指令以后,CPU会回到操做系统。当write()这个系统调用执行完以后,操做系统会调用一个特权指令(在MIPS里是rett指令),试图回到user mode。这个时候CPU又会trap到VMM,由VMM来完成最终的模式转换。

为何VMM可以知道操做系统的trap handler在哪?系统中先有VMM。当你在VMM上安装操做系统的时候,操做系统会尝试调用特权指令安装trap handler。由于有最高特权的VMM其实是监视着这一切的,因此它能够记录下trap handler的位置就好了。

总的说来,VMM占据了CPU的最高特权,使得在更低特权等级的操做系统没法进行有害操做,而且在实际环境中完成操做系统的需求。进程

 

有那么多个操做系统一块儿运行,内存是怎么管理的?

在没有VMM的时候,系统中有两种内存地址:虚拟地址(virtual address)和物理地址(physical address)。从虚拟地址到物理地址的转换有两种方式。方式一:在TLB(translate lookside buffer,硬件实现)查找。方式二:在页表(page table)中查找,找到以后把结果放到TLB中去。系统会先尝试方式一,要是找不到(TLB miss),就用方式二。ip


new6
在有了VMM以后,系统中有三种内存地址:虚拟地址(virtual address),物理地址(physical address)和机器地址(machine address)。机器地址才是真正与内存条上的地址一一对应的。物理地址只是操做系统认为的物理地址。
new5
当操做系统试着要使用特权指令来完成一个虚拟地址到物理地址的转换时(TLB miss),VMM就介入了(VMM监视着全部对特权寄存器的操做)。VMM会先使用操做系统内的代码来先完成虚拟地址到物理地址的转化(由于VMM并不知道这个映射关系)。而后,操做系统认为本身已经完成了转化,尝试去更新TLB(特权操做)。这个时候,VMM会介入,用一个叫个pmap的映射表找到物理地址对应的机器地址,用机器地址替换掉物理地址,而后把TLB更新为虚拟地址到机器地址的映射。以后,全部对这个虚拟地址的访问都会被转换为对相应机器地址的访问。(注意,MIPS用的是software-reloaded TLB,x86用的是hardware-reloaded TLB)内存

 

多个VM之间是怎么分享资源的?或者说,1GB内存怎么当2GB用?

咱们知道,每个虚拟机都要占用大量的内存空间。在内存有限的状况下,怎么在一台机器运行更多的虚拟机?幸运的是,不用的虚拟机之间在内存中数据可能会彻底一致(好比,系统文件在内存中的缓存)。如要咱们能够只在内存中保留一份数据,咱们就行节省不少空间。Disco使用虚拟IO设备和虚拟网络设备来节省内存空间。


new7

虚拟IO设备:当两个虚拟机从同一个磁盘上读同一个文件时,VMM会intercept DMA,而后就会发现这两个VM在使用一样的数据。这份数据只须要在机器内存里保存一份,而后修改pmap,使得两个VM的物理地址指向同一个机器地址就能够了。当任何一个VM更新这份数据,VMM会给它一份新的拷贝,原来的那份不作更改(copy on write机制)。 虚拟网络设备:当使用NFS从VM1向VM2复制文件时,文件并无被真正地复制。虚拟网络设备会更新VM2上的pmap,使之指向在内存中的文件,使得VM2上的操做系统认为本身已经有了这个文件。后来,VMWare还有用hash来找相同的内存页而后再共享的技术。

相关文章
相关标签/搜索