虚拟化技术相关

本文的目的是弄明白虚拟化相关的一些技术概念,KVM,QEMU, hypervisor, libvirt,virt-manager, XEN等等。

我们先整体的理解一下这些概念。

virt-manager是类似与virtual-box,vm-ware等的虚拟机软件,图形化的一个东西,通过它你可以图形话的方式来创建虚拟机,并运行虚拟机。libvirt是被virt-manager调用的一个驱动。 libvirt的作用是封装了更底层的kvm或者XEN的接口。KVM ,XEN其实都属于一种hypervisor. hypervisor的底层就是硬件了,所以hypervisor的作用是管理调用硬件。

然后自下而上,逐步理解

物理服务器或物理服务器

没什么好说的,虚拟化最底层的自然是硬件。

hypervisor

硬件之上就是hypervisor了。Hypervisor是一种运行在物理服务器和操作系统之间的中间软件层,可允许多个操作系统和应用共享一套基础物理硬件,因此也可以看作是虚拟环境中的“元”操作系统,它可以协调访问服务器上的所有物理设备和虚拟机,也叫虚拟机监视器(Virtual Machine Monitor)。Hypervisor是所有虚拟化技术的核心。非中断地支持多工作负载迁移的能力是Hypervisor的基本功能。当服务器启动并执行Hypervisor时,它会给每一台虚拟机分配适量的内存、CPU、网络和磁盘,并加载所有虚拟机的客户操作系统。

如图所示,hypervisor下面是物理服务器,上面运行着各个虚拟机。可以理解为hypervisor可以用软件模拟出硬件如cpu,网卡内存等提供给vm使用。 目前(04302015)主流的hypervisor是VMware vSphere微软Hyper-VCitrix XenServer 、IBM PowerVM、Red Hat Enterprise Virtulization、Huawei FusionSphere、开源的KVMXenVirtualBSD等。

libvirt

hypervisor之上是libvirt。我们知道 hypervisor是一个软件中间层的统称,有着多种实现,比如KVM,XEN等。那么不同实现之间的接口也肯定不同。那么libvirt的作用就是封装这些不同 hypervisor的接口,对外提供统一的接口。libvirt是linux下c语言编写的开源库。通过这个库,你可以不必关心底层的hypervisor是什么实现,只是调用libvirt的标准接口来编程。

virt-manager, virtsh

libvirt之上就是virt-manager了。我们知道libvirt是封装不同hypervisor的一个驱动接口,那么virt-manager就是利用这个标准接口编写出来的虚拟机管理软件。通过virt-manager你可以方便的创建管理虚拟机。假设没有libvirt,virt-manager的编写者可就费劲了,需要了解不同hypervisor对外提供的接口与机制。 你可以把virt-manager理解为windows上常用的virtual-box或 vmware虚拟机管理软件。virsh是virt-manager的命令行模式。

KVM和Xen

hypervisor是一个软件层,具体的实现有kvm和xen等。那么KVM和XEN有什么区别呢?

xen是自定制的hypervisor,对硬件的资源管理和调度,对虚拟机的生命周期管理等,都是从头开始写的。  KVM全称是Kernel-based Virtual Machine, kernel代表的是Linux kernel。KVM是一个特殊的模块,Linux kernel加载此模块后,可以将Linux kernel 变成hypervisor,因为Linux kernel已经可以很好的实现对硬件资源的调度和管理,KVM只是实现了对虚拟机生命周期管理的相关工作。 KVM的初始版本只有4万行代码,相对于xen的几百万行代码显得非常简洁。简单的说,XEN是一个完整的hypervisor,KVM是linux的一个模块。加载了KVM后,可以把linux内核变成hypervisor,因为KVM自己没有实现进程调度等功能,需要使用linux自己kernal的。

KVM 和 QEMU

我们已经知道KVM是linux的一个内核模块而已,那么它就是运行在内核态的一个工具。用户没办法直接控制内核,所以它还需要一个用户态的工具集。这就是QEMU-KVM了。关于用户空间的工具,KVM 的开发者选择了已经成型的开源虚拟化软件 QEMU.QEMU 是一个强大的虚拟化软件,它可以虚拟不同的 CPU 构架.   运行在内核态的KVM模块通过/dev/kvm字符设备文件向外提供操作接口.KVM通过提供libkvm这个操作库,将/dev/kvm这一层面的ioctl类型的API转化成为通常意义上的函数API调用,提供给QEMU的相应适配层.    比如说在x86 的CPU上虚拟一个Power的CPU,并利用它编译出可运行在 Power上的程序.KVM使用了QEMU的基于x86的部分,并稍加改造,形成可控制KVM内核模块的用户空间工具QEMU-KVM.所以Linux发行版中分为kernel部分的KVM内核模块和QEMU-KVM工具.这就是KVM和QEMU 的关系。

用户态和内核态

内核态: CPU可以访问内存所有数据, 包括外围设备, 例如硬盘, 网卡. CPU也可以将自己从一个程序切换到另一个程序

用户态: 只能受限的访问内存, 且不允许访问外围设备. 占用CPU的能力被剥夺, CPU资源可以被其他程序获取

为什么要有用户态和内核态

由于需要限制不同的程序之间的访问能力, 防止他们获取别的程序的内存数据, 或者获取外围设备的数据, 并发送到网络, CPU划分出两个权限等级 -- 用户态 和 内核态

用户态与内核态的切换

所有用户程序都是运行在用户态的, 但是有时候程序确实需要做一些内核态的事情, 例如从硬盘读取数据, 或者从键盘获取输入等. 而唯一可以做这些事情的就是操作系统, 所以此时程序就需要先操作系统请求以程序的名义来执行这些操作.

这时需要一个这样的机制: 用户态程序切换到内核态, 但是不能控制在内核态中执行的指令

这种机制叫系统调用, 在CPU中的实现称之为陷阱指令(Trap Instruction)

他们的工作流程如下:

  1. 用户态程序将一些数据值放在寄存器中, 或者使用参数创建一个堆栈(stack frame), 以此表明需要操作系统提供的服务.
  2. 用户态程序执行陷阱指令
  3. CPU切换到内核态, 并跳到位于内存指定位置的指令, 这些指令是操作系统的一部分, 他们具有内存保护, 不可被用户态程序访问
  4. 这些指令称之为陷阱(trap)或者系统调用处理器(system call handler). 他们会读取程序放入内存的数据参数, 并执行程序请求的服务
  5. 系统调用完成后, 操作系统会重置CPU为用户态并返回系统调用的结果
原文地址:https://www.cnblogs.com/kramer/p/4469130.html