1.KVM架构
KVM 基本上有两个组件构成:架构
1. kvm 驱动 如今已是Linux内核的一个模块了,它的做用主要是负责虚拟机的建立,虚拟内存的分配 虚拟CPU寄存器的读写和虚拟cpu的运行函数
2. 另外一个组件是 Qemu QEMU是一个通用的开源机器模拟器和虚拟器,其主要的功能是用于模拟虚拟机的用户空间组件,提供io 设备模型,访问外设的途径oop
Qemu 是什么?性能
Qemu 是纯软件设计的虚拟化模拟器,几乎能够模拟任何硬件设备,咱们最熟悉的就是可以模拟一台可以独立运行操做系统的虚拟机,虚拟机认为本身和虚拟机打交道,但实际上是和Qemu模拟出来的硬件打交道,Qemu 将这些真正的指令转译给真正的硬件ui
正由于Qemu是纯软件实现的,全部的指令都要通过qemu过一手,性能很是低,因此,在生产环境中,因此在生产环境中,Qemu配合KVM来完成虚拟化工做,由于kvm是硬件辅助的虚拟化技术,主要负责比较繁琐的cpu虚拟化和内存虚拟化,而QEMU则负责IO设备虚拟化,二者合做发挥自身的优点,相得益彰spa
从本质上看,虚拟出的每一个虚拟机对应宿主机上的一个QEMU 进程,而虚拟机的执行线路(cpu线路,io线路)对用qemu 进程中的一个线程,操作系统
下面经过启动一个虚拟机来说解kvm 与QEmu是怎么交互工做的线程
// 第一步,获取到 KVM 句柄翻译
kvmfd = open("/dev/kvm", O_RDWR);设计
// 第二步,建立虚拟机,获取到虚拟机句柄。
vmfd = ioctl(kvmfd, KVM_CREATE_VM, 0);
// 第三步,为虚拟机映射内存,还有其余的 PCI,信号处理的初始化。
ioctl(kvmfd, KVM_SET_USER_MEMORY_REGION, &mem);
// 第四步,将虚拟机镜像映射到内存,至关于物理机的 boot 过程,把镜像映射到内存。
// 第五步,建立 vCPU,并为 vCPU 分配内存空间。
ioctl(kvmfd, KVM_CREATE_VCPU, vcpuid);
vcpu->kvm_run_mmap_size = ioctl(kvm->dev_fd, KVM_GET_VCPU_MMAP_SIZE, 0); // 第五步,建立 vCPU 个数的线程并运行虚拟机。
ioctl(kvm->vcpus->vcpu_fd, KVM_RUN, 0);
// 第六步,线程进入循环,并捕获虚拟机退出缘由,作相应的处理。
for (;;) { ioctl(KVM_RUN) switch (exit_reason) {
case KVM_EXIT_IO: /* ... */ case KVM_EXIT_HLT: /* ... */
} }
// 这里的退出并不必定是虚拟机关机,
// 虚拟机若是遇到 I/O 操做,访问硬件设备,缺页中断等都会退出执行,
// 退出执行能够理解为将 CPU 执行上下文返回到 Qemu。
Qemu 软件实现虚拟化的思路是二进制指令翻译技术,主要是提取客户端的代码指令,而后将其翻译成TCG中间代码,最后再将中间代码 翻译成物理机指定架构的代码,如X86体系就翻译成其支持的代码形式,ARM架构同理,
因此,从宏观上看,源码结构主要包含如下几个部分:
· /vl.c:最主要的模拟循环,虚拟机环境初始化,和 CPU 的执行。
· /target-arch/translate.c:将 guest 代码翻译成不一样架构的 TCG 操做码。
· /tcg/tcg.c:主要的 TCG 代码。
· /tcg/arch/tcg-target.c:将 TCG 代码转化生成主机代码。
· /cpu-exec.c:主要寻找下一个二进制翻译代码块,若是没有找到就请求获得下一个代码块,而且操做生成的代码块。
其中,涉及的主要几个函数以下:
函数 |
路径 |
注释 |
main_loop |
{/vl.c} |
不少条件的判断,如电源是否断等 |
qemu_main_loop_start |
{/cpus.c} |
分时运行 CPU 核 |
struct CPUState |
{/target-xyz/cpu.h} |
CPU 状态结构体 |
cpu_exec |
{/cpu-exec.c} |
主要的执行循环 |
struct TranslationBlock |
{/exec-all.h} |
TB(二进制翻译代码块) 结构体 |
cpu_gen_code |
{translate-all.c} |
初始化真正代码生成 |
tcg_gen_code |
{/tcg/tcg.c} |
tcg 代码翻译成 host 代码 |
知道了这个整体的代码结构,再去具体了解每个模块可能会相对容易一点。
KVM做用
kvm基本结构
Kvm 已是内核模块,被看做是一个标准的Linux字符集设备 /dev/kvm
Qemu 经过kvmlib接口,用fd 经过ioctl 向设备驱动来发送建立,运行虚拟机命令,设备驱动/dev/kvm 就会来解析命令(kvm_dev_ioctl 在函数kvm_main.c中)
如下为kvm_dev_ioctl函数 执行的整个代码流程:
Kvm 模块让Linux 主机成为一个虚拟机监视/管理器(VMM),而且在原有的Linux 两种执行模式的基础上,新增长了客户模式,客户模式拥有本身的用户模式和内核模式,在虚拟机运行时,
三种运行模式分别为:
内核模式: 实现客户模式的切换,处理由于IO或者其余指令引发的客户模式退出(VM_EXIT) kvm 工做在 这 个模式下,
用户模式:表明用户在IO模式下,执行QEMU 指令;
客户模式:执行非IO的客户代码,虚拟机运行在这种模式下
在kvm的模型中,每个guest os 都是做为一个标准的Linux进程,均可以使用Linux进程管理管理命令!
这里假如Qemu 经过ioctl 发出KVM_CREAT_VM指令,建立一个VM后,qemu须要发送一个命令给VM,如KVM_CREAT_VCPU,这些命令固然也是经过ioctl发送的,用户程序中用ioctl经过发送KVM_CREAT_VM 指令后获得的返回值就是fd(KVM_VM),fd是建立的指向特定虚拟机实例的文件描述符,以后利用这个fd发送命令给VM进行访问控制。KVM 解析这些命令kvm_vm_ioctl
2.KVM工做原理
Kvm 工做原理的基本阐释:
用户模式的qume利用libkvm 经过ioctl进入内核模式,kvm 模块为虚拟机建立虚拟内存,虚拟cpu后执行VMLUACH指令进入客户模式。加载guest os并执行。若是guest os 发生外部中断,或者影子页表缺页之类的状况,会暂停guest os的执行,退出客户模式出行异常处理,以后从新进入客户模式,执行客户代码,若是发生iO事件或者信号队列中有信号到达,就会进入用户模式处理。
处理状况以下图
什么是虚拟机管理器vmm ,虚拟机管理器(vmm)有哪些,区别是什么?
虚拟机管理器(virtual machine monitor)是一个宿主程序,它支持一台计算机执行多个彻底相同的执行环境,每位用户都会感受本身在一台独立的计算机上,与其余用户相隔离的计算机上操做,尽管事实上为每位用户提供服务的都是同一台机器,在此种状况下,一台虚拟机就是由一个潜在的控制程序管理的操做系统
Vmm 是在底层对其上的虚拟机的管理和支持,之前的虚拟机必须如今一个做系统上安装虚拟机操做软件,而后再在操做软件上安装虚拟机,安装系统和应用。但如今的intel 的cpu 已经对虚拟化技术作了硬件支持,大多数的vmm可直接装在裸机上,在其上在安装几个虚拟机,这样就大大提高了虚拟化环境下的性能体验