虚拟化(1):前言

1. 前言

《系统虚拟化:原理与实现》笔记:

具体来说,虚拟化技术的实现形式是在系统中加入一个虚拟化层,虚拟化层将下层的资源抽象成另一形式的资源,提供给上层使用。通过空间上的分割、时间上的分时以及模拟,虚拟化可以将一份资源抽象成多份。反过来,虚拟化也可以将多份资源抽象成一份。

虚拟化技术成熟的时机真正到来,发生在**硬件虚拟化技术**的诞生之后(如Intel VT技术和AMD SVM技术)

计算机系统的各个抽象层

  • 硬件抽象层(Hardware Abstraction Layer, HAL) 是计算机中软件所能控制的硬件的抽象接口(如CPU寄存器、内存管理模块、I/O端口和内存映射的I/O地址[1]等)
  • API抽象层抽象的是一个进程所能控制的系统功能的集合, 包括创建进程、申请和归还内存、进程间同步与共享等

1.1 硬件抽象层上的虚拟化

​ 硬件抽象层上的虚拟化是通过抽象硬件抽象层来实现虚拟机, 为客户机操作系统呈现和物理硬件相同或相近的硬件抽象层. 由于客户机操作系统所能看到的是硬件抽象层, 因此客户机操作系统的行为和在物理平台上没有什么区别.

​ 硬件抽象层中,Host和Guest的ISA(Instruction Set Architectrue, 指令集架构)一般是一样的. Guest OS的大部分指令都可以在宿主机处理器上直接运行,只有那些需要虚拟化的指令才会由虚拟化软件进行处理, 从而大大降低虚拟化开销.

​ Guest和Host的硬件抽象层的某些部分如中断控制器、设备等,可以是完全不同的,当客户机对硬件抽象层访问时,虚拟化软件需要对此进行截获并模拟。

1.2 操作系统层上的虚拟化

​ 操作系统层上的虚拟化是指操作系统的内核可以提供多个相互隔离的用户态实例,这些用户态实例(通常而言被称为容器/container)对于它的用户而言就像真的计算机,有自己独立的操作系统, 网络, 系统设置和库函数.

​ 这种技术可以认为是UNIX系统chroot[2]命令的延伸, 因为这是操作系统内核主动提供的虚拟化, 因此操作系统层上的虚拟化也非常高效, 它的虚拟化资源和性能开销非常小, 也不需要有硬件的特殊支持. 但是灵活性较小, 每个容器中的操作系统必须和宿主机是同一类操作系统(注意是同一类, 至于什么能归为一类则要更细的划分了)

1.3 库函数层上的虚拟化

​ 操作系统通过应用级的库函数提供给应用程序一组服务, 例如文件操作服务\时间操作服务等。例如,wine是在Linux上模拟了Windows的库函数接口,使得WIndows程序能够在Linux上正常运行。

1.4 编程语言层上的虚拟化

​ 如JVM(Java Virtual Machine)和微软的CLR(Common Language Runtime)。这类虚拟机运行的是一个进程级的作业,所不同的是这些程序所针对的不是一个硬件上存在的体系结构,而是一个虚拟体系结构。


系统虚拟化

理论上来说,虚拟机和物理机可以是两个完全不同的ISA系统,但是不同的ISA使得虚拟机的每一条指令都需要在物理机上模拟执行,从而造成性能的极大下降。相同体系架构的系统虚拟化通常会有较好性能, 实现起来也更简单.

1974年, Popek和Goldberg定义了虚拟机可以看作是物理机的一种高效隔离复制.

上面蕴含了虚拟机的三个典型特征: 同质、高效和资源受控。

系统虚拟化

上图中虚拟化层也被称为VMM(Virtual Machine Monitor), 通过虚拟化层的模拟, 虚拟机中的操作系统认为自己仍然是独占一个系统在运行. 只要两台机器提供相同的虚拟硬件抽象层,虚拟机可以在两者之间进行无缝地迁移。

2. x86概要

2.1 x86内存架构

2.1.1 地址空间:

  1. 物理地址空间

​ 硬件平台可以简单的划分为三部分:CPU、内存和其他硬件设备。在CPU眼中,内存和其他硬件设备都属于可以使用的资源,这些资源组合在一起,分布在CPU的物理地址空间中。物理地址空间的大小,由CPU实现的物理地址位数决定,但物理地址的位数和CPU处理数据的能力(即CPU位数没有必然的联系), 如16位的8086CPU具有20位的地址空间。

​ 在这里,可以用内存映射I/O来举例,如一个CPU的物理地址空间为4GB,有512MB的内存,其他硬件设备寄存器被映射到512MB的I/O地址内,则该平台的物理地址空间中有1GB的元素是有效的,其余部分不存在。

  1. 线性地址空间

​ 一个平台只能有一个物理地址空间,但是每个程序都认为自己独享了整个平台的硬件资源, 为了让多个程序能够相互隔离并安全地使用物理地址空间的资源, 于是引入了线性地址空间的概念.

​ 线性地址空间的大小同样取决于CPU实现的线性地址位数, 例如32位线性地址的CPU具有4GB大小的线性地址空间. 注意, 线性地址空间的大小和物理地址空间大小没有必然联系, 如Intel的PAE平台有4GB的线性地址空间, 64GB的物理地址空间.

​ 线性地址空间会被映射到物理地址空间的某一部分或者整个物理地址空间, CPU负责将线性地址转换成物理地址, 使程序能够正确访问到该线性地址空间所映射.

线性地址空间

2.1.2 地址:

  1. 逻辑地址

​ 由于x86特殊的段机制, 还有一种逻辑地址, 即程序直接使用的地址, 由段选择符和偏移量(32位平台中是32位)构成. 在C语言中, 指针实际上存储的是逻辑地址的偏移部分, 而该偏移对应的段选择符位于段寄存器中.

  1. 线性地址(虚拟地址)

​ 线性地址是逻辑地址转换后的结果, 用于索引线性地址空间. 当CPU使用分页机制时, 线性地址必须转换成物理地址才能访问平台内存或硬件设备才能访问内存和硬件设备; 当分页机制未启用时, 线性地址相当于物理地址. 有关分段和分页可见[3]

  1. 物理地址

​ 这是CPU提交到总线用于访问平台内存和硬件设备的最终地址, 它和上面两个地址有如下关系:

  • 分段机制启用, 分页未启用时: 逻辑地址 \rightarrow 线性地址 = 物理地址
  • 分段机制和分页机制都启动: 逻辑地址 \rightarrow 线性地址 \rightarrow 物理地址

这里可以停下来思考一下, 逻辑地址是否是应用程序中(高级语言编程)使用的相对地址, 而线性地址对应整个进程使用的相对地址, 而物理地址就是最终内存中实际地址?

知识补充: 总线地址

在x86下, 设备寄存器的物理地址和寄存器在设备上的地址是不同的, 存在一个映射关系(由电子线路负责转换), 对CPU是透明的, 而CPU用于访问设备的物理地址是设备寄存器展现给总线的地址, 所以在x86下有时也称物理地址为总线地址

2.1.3 x86内存管理机制

1. 分段机制

分段机制: 将内存划分成以起始地址(Base)和长度(Limit)描述的块, 这些内存块就被称为段.

分段机制由4个基础部分组成:

  • 逻辑地址
  • 段选择寄存器
  • 段描述符
  • 段描述符表

分段机制

​ 段选择符(segment selector): 是逻辑地址的一个组成部分, 共16位, 用来索引段描述表以获得该段对应的段描述符. 段选择符中有标识段表的字段, 是用本地段表还是全局段表, 以及其他控制字段. 为了CPU能够快速获得段选择符, x86架构提供了6个段寄存器(segment register)用于存放当前程序的各个段的段选择符.

  • CS(code-segment, 代码段): 存放代码段的段选择符
  • DS(data-segment, 数据段): 存放数据段的段选择符
  • SS(stack-segment, 栈段): 存放栈的段选择符
  • ES、FS、GS:供程序自由使用,可以存放额外3个数据段的段选择符。

​ 段描述符(segment descriptor): 段描述符记录了各个段的基地址, 长度各种属性.

​ 段描述表(简称段表), x86架构提供两种段描述符表, 分别是: 全局段描述符表(Global Descriptor Table) 和 本地段描述符(Local Descriptor Table). 系统中至少有一个GDT可以被有所进程访问, 同时系统中可以有一个或多个LDT被某个进程私有或者在若干进程之间共享. GDT是内存中的一个数据结构, 类似数组, 而LDT是一个段, 它的段描述符保存在GDT中.

2. 分页机制

分页机制让现代操作系统中的虚拟内存称为可能, 一个页面可以存在于物理内存中, 也可以存放在磁盘的交换区域中, 程序可以利用比机器物理内存更大的内存区域.

​ 分页机制的核心思想是通过页表将线性地址转换位物理地址, 并配合旁路转换缓冲区(Translation Lookaside Buffer, TLB)来加速地址转换过程. 这里对分页和分段不做详细描述, 会单独深入了解这两个关键机制.

分页机制

2.2 x86架构的基本运行环境

2.2.1 三种基本模式:

x86实际上有4种运行模式: 实模式、保护模式、SMM模式和虚拟8086模式。除了SMM模式外,其余三种模式均常见于书本中。

  1. 实模式(Real Mode):当CPU加电并经历最初的混沌状态后,首先进入的就是实模式,他是早期intel 8086处理器工作的模式。在该模式下,逻辑地址转换后即为物理地址,CPU可以访问1MB的物理地址空间(实际是1MB+64KB)。操作系统或BIOS通常在该模式下准备必要的数据结构和初始化关键的寄存器,然后切入保护模式。
  2. 保护模式(Protect Mode):操作系统运行时最常用的模式,在该模式下,CPU的所有功能几乎都能得到使用,可以访问架构允许的所有物理地址空间(例如x86是4GB)。
  3. 虚拟8086模式(Virutal 8086 mode):为了早期的程序能够在保护模式下运行,x86提供了8086模式。该模式可以让CPU在保护模式下为8086程序虚拟实模式的运行环境,使这些程序在执行时无须真正的从保护模式切换到实模式。

2.3 其他:

​ 诸如I/O、中断、寄存器、总线相关内容过于繁复,由于此时重心在虚拟化方面,关于操作系统相关知识我们可以在需要时进行补充。


虚拟化(1):前言
https://www.torch-fan.site/2022/07/14/虚拟化-1-前言/
作者
Torch-Fan
发布于
2022年7月14日
更新于
2022年11月15日
许可协议