系统虚拟化基本概念与发展历史和趋势展望
系统虚拟化基本概念与发展历史和趋势展望
系统虚拟化(System Virtualization)已成为当前支撑云计算、大数据、移动互联网和工业互联网等新型计算和应用模型的关键技术,应用于从云数据中心到边缘智能终端等不同硬件尺度的“云-网-边-端”全场景中。
系统虚拟化基本概念
虚拟化(Virtualization)泛指将物理资源抽象成虚拟资源,并在功能和性能等方面接近物理资源的技术,即“功能不缺失、性能不损失”。
虚拟化技术广泛应用于从硬件到软件的不同计算机系统层次,例如 物理内存抽象成虚拟内存 , 设备抽象成文件 ,物理 显示器抽象成窗口 (Window),Java应用运行于JVM(Java Virtual Machine,Java虚拟机)。
一般而言,计算机系统自下而上被划分为多个层次(见图1-1)。
指令集抽象ISA
硬件向上对软件提供的指令集抽象ISA(Instruction Set Architecture,指令集架构)通常分为 系统ISA(System ISA)和用户ISA(User ISA) 。
系统ISA提供特权操作(如切换进程页表),一般在操作系统内核态运行;
用户ISA提供给普通应用程序使用(如进行加法操作),一般在用户态运行。
例如,RISC-V的指令集手册提供第一卷——用户态ISA(User-Level ISA)和第二卷——特权(系统)架构(Privileged Architecture),分别对应于用户ISA和系统ISA。
因此,两者合起来构成完整的硬件编程接口, 即ISA=System ISA+User ISA。
操作系统(OS)
OS(Operating System,操作系统)运行于硬件之上,向下管理硬件资源、向上提供系统调用(System Calls)接口。
操作系统提供的 系统调用 (上层应用可以通过系统调用请求操作系统执行特权操作,即执行系统ISA)以及 用户ISA共同组成了应用程序的ABI (Application Binary Interface,应用程序二进制接口)。
如果两个系统的ABI相同,意味着提供了一个可移植的基础运行环境,即ABI=System Calls+User ISA。
库程序调用(Library Calls)
库程序调用(Library Calls)提供系统运行时(Runtime)、系统公共服务(Services)和功能丰富的第三方程序(如数学库、图形库等), 运行于用户态,以函数库的形式供应用程序调用 。
同时, 应用程序一般通过库函数调用操作系统的系统调用接口 。因此,对于应用程序而言, 底层的系统ISA和操作系统的系统调用是透明的 ,它主要关心运行环境(包括运行时、服务和库等)提供的API(Application Program Interface,应用程序编程接口)。
也就是说, 确定了应用程序所使用的用户ISA和所调用的库函数(包括动态库和静态库) ,也就确定了应用程序的用户态编程接口, 即API=Library Calls+User ISA。
因此,如图1-2所示, 硬件和软件资源在不同层次的抽象对应不同的虚拟化方法 。
物理硬件层的虚拟化
虚拟机监控器Hypervisor通过直接对硬件资源进行抽象和模拟 ,提供了虚拟硬件ISA(Virtual ISA)接口,包括虚拟系统ISA(Virtual System ISA)和虚拟用户ISA(Virtual User ISA),即Virtual ISA=Virtual System ISA+Virtual User ISA。
Hypervisor有时也称为VMM(Virtual Machine Monitor,虚拟机监控器),除非专门列出(例如Rust-VMM是用Rust语言编写的用户态虚拟机监控程序),本书统一采用Hypervisor表述VMM。
由于虚拟化技术的多样性,操作系统还可以进一步细分为宿主机操作系统(Host OS)和客户机操作系统(Guest OS),这将在1.3节详细介绍。
虚拟硬件ISA提供了完整的硬件资源抽象,从而使多个操作系统能够运行其上并共享硬件资源,例如VMware虚拟化产品VMware Workstation可以在Windows系统上运行一个Linux操作系统。
操作系统层的虚拟化
操作系统本身就是虚拟化技术的一种体现, 它将CPU、内存和I/O等资源进行了抽象,最终以进程为单位使用这些资源,并进一步由命名空间(Namespace)和控制组(Cgroups)等容器(Container)技术实现对资源的隔离和限制 。
因此这一层次的虚拟化 也称为轻量级虚拟化、进程虚拟化 。有些文献把基于二进制翻译的方法运行相同或不同ISA的二进制程序称为进程虚拟化,例如在基于x86的Windows系统上运行ARM架构的程序。
本书采用的术语容器虚拟化主要指基于同构指令集的轻量级虚拟化方法,它提供了虚拟ABI(Virtual ABI)接口,**即Virtual ABI=虚拟系统调用(Virtual System Calls)+Virtual User ISA。**近年比较流行的Docker技术便属于容器虚拟化方法。
应用层程序运行环境的虚拟化
应用程序本身作为虚拟机(也称为沙箱,Sandbox),提供用户态虚拟运行时(Virtual Runtime)支撑应用程序的运行,即虚拟API接口=虚拟库程序调用(Virtual Library Calls)+Virtual User ISA。
比较常见的是高级编程语言的虚拟运行环境,例如Java虚拟机和Python虚拟机。注意,这里的 用户态ISA有时采用高级编程语言自定义的字节码(Bytecode)抽象 ,用于屏蔽各个硬件指令集的差异,能够跨平台运行**(最终会将字节码编译到某个具体硬件架构的用户态ISA)。**
以上是三种基本的虚拟化抽象方法, 根据指令集、操作系统是否同构等不同存在多种变体 。
例如库函数虚拟化:通过拦截用户态程序的系统调用,随后对调用进行仿真和模拟,能够在同一个硬件指令集上运行不同操作系统的程序。
例如,Wine基于Linux等操作系统运行Windows的应用软件(通过提供兼容层将Windows的系统调用转换成与Linux对应的系统调用)。
从ABI角度分析Wine,用户ISA同构(均为x86指令集),但系统调用异构(分别为Windows与Linux)。
近年日益流行的轻量级Unikernel是一种定制的库操作系统(Library OS)。Unikernel和应用程序一起编译打包,构成单地址空间的可执行二进制镜像,不再严格区分用户态和内核态。
因此,Unikernel可以直接运行在硬件或Hypervisor上,就硬件接口而言,Unikernel的CPU和内存部分仍为(高度简化的)虚拟硬件I