kvm架构详解

1. 简介

当前的主流虚拟化实现技术分为两种:
VMM(虚拟化监控器)运行在硬件平台上,控制所有硬件并管理guest os。guest os运行在比VMM更高的级别。例如xen。
VMM运行在宿主操作系统上,宿主操作系统作为第一软件层,VMM作为第二软件层,guest os作为第三软件层。例如kvm和virtual box。

kvm
在这里插入图片描述
KVM是集成到Linux内核的Hypervisor,是X86架构且硬件支持虚拟化技术(Intel VT或AMD-V)的Linux的全虚拟化解决方案。它是Linux的一个很小的模块,利用Linux做大量的事,如任务调度、内存管理与硬件设备交互等。

xen
在这里插入图片描述
Xen是第一类运行在裸机上的虚拟化管理程序(Hypervisor)。它支持全虚拟化和准虚拟化,Xen支持hypervisor和虚拟机互相通讯,而且提供在所有Linux版本上的免费产品,包括Red Hat Enterprise Linux和SUSE Linux Enterprise Server。
Xen最重要的优势在于准虚拟化,此外未经修改的操作系统也可以直接在Xen上运行(如Windows),能让虚拟机有效运行而不需要仿真,因此虚拟机能感知到Hypervisor,而不需要模拟虚拟硬件,从而能实现高性能。

2. kvm模块

KVM是一个基于宿主操作系统的虚拟机。在这里,我们再一次看到了实用至上的Linux设计哲学。主要部分是一个内核模块,其他的部分则尽可能充分利用Linux内核的既有实现,最大限度地重用代码。
KVM本身不执行任何设备模拟,需要用户空间程序QEMU通过/dev/kvm接口设置一个虚拟客户机的地址空间,向它提供模拟的I/O设备,并将它的视频显示映射回宿主机的显示屏。
KVM模块是KVM虚拟机的核心部分。其主要功能是初始化CPU硬件,打开虚拟化模式,然后将虚拟客户机运行在虚拟机模式下,并对虚拟客户机的运行提供一定的支持。

初始化CPU硬件

为了软件的简洁和性能,KVM仅支持硬件虚拟化。自然而然,打开并初始化系统硬件以支持虚拟机的运行,是KVM模块的职责所在。
以KVM在Intel公司的CPU上运行为例。

  1. 在被内核加载的时候,KVM模块会先初始化内部的数据结构;
  2. 做好准备之后,KVM模块检测系统当前的CPU,然后打开CPU控制寄存器CR4中的虚拟化模式开关,并通过执行VMXON指令将宿主操作系统(包括KVM模块本身)置于虚拟化模式中的根模式;
  3. 最后,KVM模块创建特殊设备文件/dev/kvm并等待来自用户空间的命令。接下来虚拟机的创建和运行将是一个用户空间的应用程序(QEMU)和KVM模块相互配合的过程。

KVM与QEMU通信

KVM模块与用户空间QEMU的通信接口主要是一系列针对特殊设备文件的IOCTL调用。
如上所述,KVM模块加载之初,只存在/dev/kvm文件,而针对该文件的最重要的IOCTL调用就是“创建虚拟机”。在这里,“创建虚拟机”可以理解成KVM为了某个特定的虚拟客户机(用户空间程序创建并初始化)创建对应的内核数据结构。
同时,KVM还会返回一个文件句柄来代表所创建的虚拟机。针对该文件句柄的IOCTL调用可以对虚拟机做相应的管理,比如创建用户空间虚拟地址和客户机物理地址及真实内存物理地址的映射关系,再比如创建多个可供运行的虚拟处理器(vCPU)。
同样,KVM模块会为每一个创建出来的虚拟处理器生成对应的文件句柄,对虚拟处理器相应的文件句柄进行相应的IOCTL调用,就可以对虚拟处理器进行管理。

CPU虚拟化

针对虚拟处理器的最重要的IOCTL调用就是“执行虚拟处理器”。
通过它,用户空间准备好的虚拟机在KVM模块的支持下,被置于虚拟化模式中的非根模式下,开始执行二进制指令。
在非根模式下,所有敏感的二进制指令都会被处理器捕捉到,处理器在保存现场之后自动切换到根模式,由KVM决定如何进一步处理(要么由KVM模块直接处理,要么返回用户空间交由用户空间程序处理)。

内存虚拟化

除了处理器的虚拟化,内存虚拟化也是由KVM模块实现的。
实际上,内存虚拟化往往是一个虚拟机实现中代码量最大、实现最复杂的部分(至少,在硬件支持二维地址翻译之前是这样的)。
众所周知,处理器中的内存管理单元(MMU)是通过页表的形式将程序运行的虚拟地址转换成为物理内存地址。在虚拟机模式下,内存管理单元的页表则必须在一次查询的时候完成两次地址转换。这是因为,除了要将客户机程序的虚拟地址转换成为客户机物理地址以外,还必须将客户机物理地址转换成为真实物理地址。
KVM模块开始使用了影子页表的技术来解决这个问题:在客户机运行时候,处理器真正使用的页表并不是客户机操作系统维护的页表,而是KVM模块根据这个页表维护的另外一套影子页表。影子页表的机制比较复杂,感兴趣的读者可以自行翻阅相关材料,这里不再展开详述。
影子页表实现复杂,而且有时候开销很大。为了解决这个问题,新的处理器在硬件上做了增强(Intel的EPT技术)。通过引入第二级页表来描述客户机虚拟地址和真实物理地址的转换,硬件可以自动进行两级转换生成正确的内存访问地址。KVM模块将其称为二维分页机制。

设备虚拟化

处理器对设备的访问主要是通过IO指令和MMIO,其中IO指令会被处理器直接截获,MMIO会通过配置内存虚拟化来捕捉。
但是,外设的模拟一般并不由KVM模块负责。一般来说,只有对性能要求比较高的虚拟设备才会由KVM内核模块来直接负责,比如虚拟中断控制器和虚拟时钟,这样可以大量减少处理器的模式切换的开销。
大部分的输入输出设备还是会交给用户态程序QEMU来负责。

3. QEMU

QEMU本身并不是KVM的一部分,其自身就是一个著名的开源虚拟机软件。与KVM不同,QEMU虚拟机是一个纯软件的实现,所以性能低下。但是,其优点是在支持QEMU本身编译运行的平台上就可以实现虚拟机的功能,甚至虚拟机可以与宿主机并不是同一个架构。
作为一个存在已久的虚拟机,QEMU的代码中有整套的虚拟机实现,包括处理器虚拟化、内存虚拟化,以及KVM使用到的虚拟设备模拟(比如网卡、显卡、存储控制器和硬盘等)。

KVM对QEMU的利用

为了简化开发和代码重用,KVM在QEMU的基础上进行了修改。
虚拟机运行期间,QEMU会通过KVM模块提供的系统调用进入内核,由KVM 模块负责将虚拟机置于处理器的特殊模式运行。
遇到虚拟机进行输入输出操作,KVM模块会从上次的系统调用出口处返回QEMU,由QEMU来负责解析和模拟这些设备。

QEMU对KVM的利用

从QEMU角度来看,也可以说QEMU使用了KVM模块的虚拟化功能,为自己的虚拟机提供硬件虚拟化的加速,从而极大地提高了虚拟机的性能。除此之外,虚拟机的配置和创建,虚拟机运行依赖的虚拟设备,虚拟机运行时的用户操作环境和交互,以及一些针对虚拟机的特殊技术(诸如动态迁移),都是由QEMU自己实现的。

QEMU和KVM的结合

从QEMU和KVM模块之间的关系可以看出,这是典型的开源社区在代码共用和开发项目共用上面的合作。诚然,QEMU可以选择其他的虚拟机或技术来加速,比如Xen或者KQEMU;KVM也可以选择其他的用户空间程序作为虚拟机实现,只要它按照KVM提供的API来设计。但是在现实中,QEMU与KVM两者的结合是最成熟的选择,这对一个新开发和后起的项目(KVM)来说,无疑多了一份未来成功的保障。

4. Intel虚拟化技术

在这里插入图片描述
Intel虚拟化技术其实可以大致分为三类:
第一类是处理器相关的,称为VT-x,是实现处理器虚拟化的硬件扩展,这也是硬件虚拟化的基础;
第二类是芯片组相关的,成为VT-d,是从芯片组的层面为虚拟化提供必要支持,通过它,可以实现诸如直接分配物理设备给客户机的功能;
第三类是输入输出设备相关的,主要目的是通过定义新的输入输出协议,使新一代的输入输出设备可以更好地支持虚拟化环境下的工作,比如Intel网卡自有的VMDq技术和PCI组织定义的单根设备虚拟化协议(SR-IOV)。

硬件虚拟化技术发展到今天,已经从最初的处理器虚拟化扩展变成了各种先进技术的集合。而且,Intel公司还在继续为这个集合添加新的成员。同时Intel公司的软件开发工程师也一直活跃在开源虚拟机社区,为KVM即时添加最新的硬件支持。

参考《KVM虚拟化技术:实战与原理解析 》

发布了65 篇原创文章 · 获赞 18 · 访问量 9万+
展开阅读全文

没有更多推荐了,返回首页

©️2019 CSDN 皮肤主题: 大白 设计师: CSDN官方博客

分享到微信朋友圈

×

扫一扫,手机浏览