Lec 6 虚拟机技术加强模块化
阅读参考书 §5.8
前面介绍多种高级抽象,用于虚拟化处理器、内存和通信链路,以实现模块化。应用程序通过Supervisor-call接口以及中断和异常处理程序与这些抽象进行交互。
另外一种方法是使用虚拟机(VM)。尽可能利用真实的物理机实现多个虚拟实例(包括特权指令、如加载和存储到页映射地址寄存器)。实现虚拟机的软件被称为虚拟机监视器(Virtual Machine monitor, VMM)
思考题
- 为什么我们希望在同一台物理机器上运行多个操作系统?
- 虚拟机监控器(VMM)的作用是什么?
- “陷入和仿真”(trap and emulate)是什么意思?
- VMM 如何处理客户操作系统的虚拟内存?
- VMM 如何处理客户操作系统的用户/内核位(U/K bit)?
- 为什么 VMM 必须参与这两件事(虚拟内存、U/K bit)?换句话说,为什么客户操作系统不能只在 VMM 拦截任何东西的情况下正常工作?
- 什么是大内核(monolithic kernel)?什么是微内核(microkernel)?它们之间的区别是什么?
- 许多操作系统是大内核,为什么?
虚拟机
用途
- 运行多个并行的guestOS
- 隔离guest OS中的错误
- 简化OS开发
实现方式
- 直接在硬件上运行(以内核模式运行监视器,用户模式下运行guest OS)
- 作为用户模式的应用程序运行在宿主OS上
第二种比较简单,因为监视器可以利用宿主OS提供的抽象,但前提是宿主OS必须将监视器所需的所有事件转发给它。为了简化,我们假设采用第一种方式。不过涉及的核心问题都是相同的。

要实现虚拟机,监视器必须提供三项核心功能:
- 计算机虚拟化。例如如果guest OS向页映射地址寄存器(PMAR)存储新的值,机爱你时期必须让Guest OS认为它成功完成了,即使它实际上运行在用户模式下
- 事件分派。例如,监视器必须将APP出发的中断、异常和Supervisor call转发到相应的Guest OS
- 资源分配。例如,监视器必须合理分配物理内存,确保多个guest OS能够共享物理资源
如果所有指令都可以虚拟化的,则计算机的虚拟化相对容易。所谓虚拟化指令就是能让监视器捕捉并模拟的指令。这些指令必须触发异常,这样监视器就能接管控制权,模拟指令执行,并恢复Guest OS的运行。
如果某条指令在用户模式和内核模式的行为不同,但不会触发异常,那么它就是不可虚拟化指令。监视器无法通过传统的方法捕获它们,因此处理非虚拟化指令需要更复杂的方案。
挑战
假设一个Guest OS实现了自己页表。为了让每个Guest OS能够访问所有的物理内存,但不能访问其他Guest的物理内存,虚拟机监视器必须保护Guest的物理地址,一个可行的方法是递归地进行地址虚拟化。也就是说,客户机和虚拟机将应用程序的虚拟地址转换为虚拟机地址;监视器再将虚拟机地址转换为物理地址。设计监视器的一个挑战在于维护从应用程序虚拟地址到虚拟机地址再到物理地址的映射。总体方案是让监视器仿真对页映射地址寄存器(page-map address register)的加载和存储操作,并为每个虚拟机维护自己的转换映射,我们称之为机器映射(machine map)
当客户机执行存储指令(store instruction)向页映射地址寄存器写入数据时,监视器可以推断出客户机正在使用的虚拟机内存,以及从虚拟地址到机器地址的映射关系。由于这条指令是特权指令,处理器会触发非法指令异常,并将控制权转移给监视器。存储指令的参数包含一个页映射表的机器地址。监视器可以读取该内存,查看客户机计划使用的虚拟机内存,以及客户机的虚拟地址到机器地址的映射关系(包括访问权限)。
对于每个机器页(包括存放客户机页映射表的页),监视器都可以分配一个物理页,并在机器映射表(machine map)中记录从虚拟地址到机器地址再到物理地址的转换关系。有了这些信息后,监视器可以构造一个新的页映射表,将客户机的虚拟地址直接映射到物理地址,并将该映射表安装到真实的页映射地址寄存器中(由于监视器运行在内核模式下,此操作可以成功)。因此,尽管系统内部有两层页映射(虚拟到机器,机器到物理),但物理处理器执行的地址转换实际上只有一层:它直接使用监视器设置的新页映射表,将应用程序的虚拟地址转换为物理地址。为了高效支持这种双重转换方案,Intel 和 AMD 已经在硬件层面提供了额外的支持。
最后一步,监视器可以让客户机操作系统从执行存储到页映射地址寄存器的指令之后的指令继续运行,从而给客户机提供一种假象:它似乎直接更新了页映射地址寄存器。随后,客户机及其应用程序便可继续正常执行。
如果客户机更改了自己的页映射表(例如,切换到另一个应用程序),监视器会通过异常捕获这一事件——因为向页映射地址寄存器存储数据的指令是特权指令,会触发异常,进而调用监视器的异常处理程序。异常处理程序会像之前一样模拟该指令的执行,即更新物理页映射地址寄存器,并恢复客户机的运行。
如果监视器需要切换到另一个客户机操作系统,它只需将页映射地址寄存器切换到新客户机的页映射表,类似于在应用程序之间切换。
如果应用程序访问了不属于自身地址空间的页,硬件会触发缺页异常(missing-page exception),这将调用监视器中的异常处理程序。随后,监视器的异常处理程序会调用相应客户机的异常处理程序。此时,客户机的异常处理程序会认为自己直接从处理器接收到了缺页异常,并采取相应的处理措施。