抽象是一种封装,而虚拟化则是在抽象基础上的复制。虚拟化通过空间上的分割、时间上的分时以及抽象模拟来将一份或多份资源抽象成新的一份或多份资源。
1 软硬件中的抽象
抽象是计算机软硬件中非常重要的概念,通过抽象的定义、软硬抽象以及硬件抽象层的介绍来比较全面的理解抽象的含义。
1.1 抽象的定义
抽象指的是在研究对象时去除物理、空间或时间的部分细节,使得注意力集中在关键细节上。John V. Guttag对抽象的定义:“抽象的本质是保留与上下文相关的信息,而忽略与上下文无关的信息”。然而,抽象并不仅仅是简单的、原有重要细节的复制;而是在此基础上,做了一层封装,使得抽象出的对象具有了一些新的特性。
抽象是一种非常强大的方法,广泛应用于计算机各个领域,例如:
- 数据抽象:通过数据类型来实现实际工作中的数据抽象,在程序中使用独立的数据结构。
- 控制抽象:过程、函数、子程序的概念,代表了程序中控制流的具体实现。
- 类的抽象:使用继承,把非抽象类,通过识别通用行为,变成抽象类的过程。
- 进程的抽象:进程分为两部分:接口和实现,接口是进程的抽象。接口提供给其他进程调用,屏蔽实现细节。
- 计算机的抽象:包括通过指令集架构抽象CPU、通过虚拟地址抽象内存、通过虚拟内存抽象外存等。
- 虚拟化:虚拟化把整个计算机抽象,并且复制多份,呈现给上层客户机OS。
1.2 软件抽象
一个软件模块会有两个方面,用户看到的是他服务的一面,而设计者看到的是它内部结构的一面。此软件模块提供的服务是基于内部结构的一个封装,是内部结构的一个抽象。
如图1,我们将客户看到的服务的一面称为模块的接口,将设计者看到的结构的一面称为模块的实现。模块抽象的原则是,客户不应该也不需要知道一个模块的具体实现就能够使用它,而设计者即使修改具体实现也不影响客户端的访问(接口不变)。
图 1 模块的抽象
例如,网络分层也是一种抽象的机制。每一层实现特定的功能,功能的具体实现封装在层的内部,对外通过抽象的接口提供服务。这样,可以在后期继续丰富层的功能,并且优化功能的具体实现;与此同时,不需要经常改变对外服务的接口。
1.3 硬件抽象层
HAL是位于驱动和操作系统内核之间的一个薄层,HAL在底层硬件和操作系统的上一层之间提供统一的接口,从而隐藏了具体的底层硬件与上一层之间的硬件差异。
如图2,HAL层的作用是消除硬件差异,为操作系统提供一致的“硬件”,统一的操作系统及应用层的代码可以用于所有硬件。所有同类型的硬件在操作系统上看起来都是一样的,因为它通过HAL的抽象之后,使得上层操作系统“看到”了接口标准的硬件。
图2 硬件抽象层在计算机系统中的位置
虽然在图2中,HAL实现了CPU、内存、MMU、定时器、接口及设备的硬件抽象,但狭义的HAL通常只包含接口及设备的硬件抽象,CPU、内存、MMU、定制器等的硬件抽象通常是集成在内核中,代表了内核对不同架构处理器的支持。
2 虚拟化抽象
抽象和虚拟化是两个密切相关的概念,通过虚拟化的概念以及抽象和虚拟化的对比来理解虚拟化抽象。
2.1 广义的虚拟化
我们通常讲的虚拟化,一般特指计算机硬件的虚拟化。虚拟化使用软件或特殊硬件在计算机硬件上创建抽象层,该抽象层将计算机(包含处理器、内存、IO设备等)划分为多个虚拟计算机。每个虚拟机都运行自己的操作系统,表现得像一台独立的计算机一样。
广义的虚拟化,指的是创建某个对象的虚拟(而非实际)版本的行为。广义虚拟化的概念,存在于计算机技术领域的很多方面,具体如表1的示例。
表1 计算机领域虚拟化技术示例
2.2 虚拟化和抽象的区别与联系
抽象是对原有对象的封装,会产生一个新的“对象”,具有一些跟原有对象不一样的特性。例如,虚拟机相比物理的计算机增加了快照、迁移、高可用等特性,这是抽象所实现的新的特性。而虚拟化可以看作是一种复制,例如虚拟化技术把单个物理的计算机虚拟化(或者说抽象后复制)成多个虚拟计算机。简而言之,虚拟化是在抽象基础上的复制,而抽象则是虚拟化的个例。
注意:复制并不意味着所有的虚拟化后资源规格是一致的。例如把物理的服务器虚拟成虚拟机,每台虚拟机的CPU核数和内存大小可以灵活配置。
在云计算领域,抽象及虚拟化的概念广泛存在。例如,通过虚拟化技术充分利用软硬件资源,给客户提供使用便捷并且成本更加低廉的服务;通过一些策略的控制,给客户提供相互隔离的并且功能强大的服务接口;屏蔽底层软硬件差异,给客户提供简单的、一致性的并且可重用的接口;呈现为IaaS、PaaS以及SaaS各种不同分层的云计算产品服务矩阵,每一个产品都实现非常复杂并且强大的功能抽象,给客户提供一致性的简单的访问接口,并且服务具有非常好的可扩展性,可以复制多份来支撑更上层的产品服务。
3 虚拟化模型
抽象和虚拟化的概念比较“抽象”,本节通过虚拟化的数据模型、架构模型和架构实现三个方面的介绍,让读者加深对虚拟化在硬件实现方面的理解。
3.1 虚拟化的数学模型
在计算机场景下,抽象和虚拟化的对象是各种各样的软硬件资源。虚拟化将下层的资源抽象成另一种形式的资源,供上层使用。虚拟化通过空间上的分割、时间上的分时共享以及抽象模拟来将一份或多份资源抽象成新的一份或多份资源。被抽象的资源可以是物理的,也可以是逻辑的。这也就意味着:虚拟化可以是多层的,也可以是嵌套的。
抽象是虚拟化的基础,抽象用数学表达式可以表示为
y=FA(x) —— 公式1
其中FA(Function for Abstract)为抽象映射函数,x为被抽象的资源,y为抽象后的资源。
虚拟化则是在抽象数学表达式公式1基础上的扩展,虚拟化的数学表达式为
(y0, y1, y2, …, yn-1) = FV(x0, x1, x2, …, xm-1) —— 公式2
其中FV(Function for Virtualization)为虚拟化映射函数,x0 到xm-1为原始资源,m为原始资源数量,y0到yn-1为虚拟资源,n为虚拟资源数量。
我们可以拆分公式2中的FV,为每一个y建立一个与所有x相关的独立的映射
yj = FVj(x0, x1, x2, …, xm-1) —— 公式3
其中,j为虚拟化后的资源y的下标(0≤j<n),FVj为yj的虚拟化映射函数。
进一步的,我们把公式3中的FVj虚拟化映射函数继续拆分,我们可以得到每个x和每个y的虚拟化映射函数
yj = FVj i(xi) = FAj i(xi) —— 公式4
其中,i为原始资源x的下标(0≤i<m),j为虚拟资源y的下标(0≤j<n),FVj i为xi到yj的一一虚拟化映射函数,FAj i为资源xi到yj的抽象映射函数。
原始资源跟虚拟资源之间的虚拟化映射可能是全相关的,也就是说,n个虚拟资源中的每一个都跟所有m个原始资源有关系。并且,我们可以建立起如公式 6.4的原始资源和虚拟资源之间的一一虚拟化映射关系。
从公式4可以看到,在两边都是单个资源的时候,其实FVj i就是FAj i。也就是说,抽象就是单一资源到单一资源的虚拟化;同时也说明,虚拟化是单一资源到单一资源的抽象映射的集合。
x=FA-1(y) —— 公式5
实际使用的时候,既需要下层到上层的映射,也需要上层到下层的映射。因此,在上层到下层的映射的时候,使用如公式5所示的抽象函数的反函数FA-1。
3.2 虚拟化的架构模型
在分层的系统里,下一层为上一层提供服务。虚拟化层,则是插入两层之间的新的一层。虚拟化层,使用下一层提供的服务,同时代替下一层为上一层提供服务。
如图3,我们通过虚拟化层,把m个原始资源虚拟成n个虚拟资源。虚拟资源会屏蔽很多原有资源的细节,保留原有资源的一些特性,同时也会具有一些新的特性。
图3 分层的虚拟化架构模型
实际上,在虚拟化层并不是直接看到实际的虚拟资源,而是只看到资源经过封装的接口。接口成为与资源交互的媒介,因此,在虚拟化层实现虚拟化,是通过对接口的虚拟化处理来实现对资源的虚拟化。
为了更好的理解虚拟化架构,图4给出了两个虚拟化整体架构的示例。图4(a)为物理的网卡被虚拟化成了4个虚拟的网卡,在虚拟化场景,就是通过软件实现这样的机制来呈现给VM独立的网卡。图4(b)为物理的3个物理磁盘被虚拟成了5个虚拟的磁盘,Linux中LVM就是通过这样的架构,实现物理磁盘到逻辑磁盘的映射。
(a) 单个物理网卡虚拟成4个虚拟网卡 (b) 三个物理磁盘虚拟成5个虚拟磁盘
图 6.4 虚拟化架构示例
3.3 虚拟化层模型的实现
如前面提到的,通过空间分割、时间分享以及抽象模拟的方式,来实现资源的虚拟化,本质上,虚拟化是是对原有资源进行空间的或时间的切分。具体阐述如下:
- 抽象是一对一的资源映射。没有资源的切分,只是资源经过封装后,抽象成了一个新的虚拟的资源。例如,我们对一个特定的IO设备通过HAL层封装成OS可以识别的标准的IO设备。
- 时间上的分时共享。是通过时间片的切分、分时共享来达到虚拟化的目的。例如,CPU的虚拟化,通过在原生CPU的基础上引入非根模式,以及vCPU等属性封装,呈现给VM操作系统一个“全新”的CPU。vCPU像线程一样,受宿主机OS的调度,分时共享物理的CPU核;但在VM操作系统看来,vCPU是一个完整运行的CPU核。
- 空间上的分割。通过把大的空间分割成小的空间,封装成不同的新的资源。例如,内存的虚拟化,则是通过把内存划分成固定大小的页,然后通过MMU和TLB把页分配给不同的进程使用。每个进程拥有自己独立的内存地址空间,在一个64位地址的系统里,每个进程理论上可以拥有264字节大小的内存空间。
因此,我们可以以资源的粒度,进行资源的一对一虚拟化映射;或者在有些场景,可以更进一步的,在资源(时间或空间)切片的粒度,进行资源切片的一对一映射。这样细粒度的资源切片的映射,可以让虚拟化实现更加均衡、更加灵活。
因为每一层的组件之间是通过接口交互的,因此也是通过接口来呈现虚拟化的。如图5,给出了原始资源接口和虚拟资源接口之间的一一映射关系。基于此映射函数实现的FA处理模块为一个通用的映射函数FA(公式4)处理,FA-1(公式5)为FA的反运算。经过FA或FA-1处理后,再通过总线互联,把具体的事务访问路由到对应的资源接口或虚拟资源接口。每个资源接口分为输入和输出两个方向的处理,因此有两套处理机制。
图5 虚拟化层的内部实现示意图
4 虚拟化加速的必要性
以Intel CPU平台为例,通过VT-x技术实现了CPU和内存的硬件(加速)虚拟化,通过VT-d以及PCIe SR-IOV等技术实现了IO接口的硬件(加速)虚拟化。而网络虚拟化(如部署在主机侧的OVS)和存储虚拟化(如本地存储LVM和分布式存储Ceph),则是云计算场景CPU资源消耗非常大的两类后台工作任务:
- 站在CPU的角度,网络和存储的虚拟化都属于IO类的处理。在添加了虚拟化层的处理堆栈里,每一次IO事务访问,都需要经过虚拟化映射处理,把对虚拟设备的事务访问转换成对物理设备的事务访问。因此,在不考虑其他因素影响的情况下,虚拟化处理的计算资源消耗跟IO的带宽是完全正比的关系。
- 随着网络的带宽从10Gbps升级到25Gbps,为了更高的PPS性能,网络虚拟化的工作任务占用的CPU已经挤占了很多本应该用于用户业务的CPU资源。未来网络带宽很快会升级到100Gbps甚至200 Gbps,相对的,未来可预见的CPU性能提升却越来越有限。这意味着网络虚拟化处理所需要的CPU核的数量,会随着网络带宽的增加几乎线性增长。
- 存储也面临同样的问题,当我们把存储介质从磁盘更新到闪存,把接口从SCSI更新到NVMe。NVMe是面向多核场景,支持多队列机制,支持PCIe,整个接口的IOPS超过百万级,存储虚拟化工作任务的CPU资源消耗也会随之显著增加。
可以说,为了应对未来越来越高的带宽、延迟等性能要求下的虚拟化处理,虚拟化相关的工作任务不得不从主机软件卸载到硬件;与此同时,通过硬件加速优化效率和成本,减轻了主机CPU的压力,这样可以把主机CPU资源尽可能多的留给用户业务。
作者:黄朝波
来源:https://mp.weixin.qq.com/s/GVCilaQra2JOuEf1xZYHcg
微信公众号:
相关文章推荐
更多软硬件技术干货请关注软硬件融合专栏。