随着计算机硬件的发展,人们对最大化利用硬件资源的需求日益迫切。从上世纪六、七十年代虚拟机概念的提出,到现在虚拟化技术的日益成熟,为人们这些需求的实现提供了有利的解决方案。基于IntelVT技术的KVM虚拟机,是一种采用硬件辅助虚拟化的全虚拟化方案,并在Linux 内核版本2.6.20 之后,以模块的形式集成到内核的各个主要发行版本。KVM虚拟机吸收了QEMU、Bochs、UML、Virtual PC 等传统虚拟机的长处和优势,利用硬件辅助的虚拟化技术,使虚拟机的大多数指令可以直接在物理处理器上运行,具有更加优越的效率和性能。为了充分利用处理器的资源,往往需要虚拟机在某一指定个核上运行,而其它的核上运行特定的任务。本文基于CPU 的亲和性(Affinity),采用进程绑定,实现了一种解决上述问题的有效方法。
1 Intel VT技术下的KVM虚拟机架构
KVM 虚拟机由两部分构成:一部分是以模块形式集成到Linux 内核的KVM Driver,负责管理虚拟硬件资源,并创建一个字符设备(/dev/kvm),通过ioctl接口与用户空间的设备通信,以及完成虚拟机内存的分配、虚拟机寄存器的读写以及虚拟机CPU 的运行等。因此,每个虚拟机被Linux 核心当作是一个标准的进程。另一个部分是KQEMU,即针对有虚拟化支持的X86 处理器而修改过的QEMU。KQEMU 主要是完成对硬件的模拟,通过/dev/kvm 与KVM Driver 交互。KVM 虚拟机架构如图1 所示:
在Intel VT-x 技术下有两种工作模式:VMX rootoperation 模式和VMX non-root operation 模式。在这两种模式下,KVM 虚拟机充分利用硬件的支持,实现了系统的虚拟化。KVM 的KVM Driver 和KQEMU分别运行于Kernel 模式的和User 模式。这里的Kernel模式和User 模式实际上指的是VMX root operation 模式下的特权级0 和特权级3。在图1 中,Linux Kernel、KVM Driver 和/dev/kvm 都属于VMX root operation 模式。另外,KVM 将客户机所在的运行模式称为Guest模式,即VMX 的VMX non-root operation 模式。
图1 KVM 虚拟机架构
2 KQEMU和KVM工作原理
Intel VT-x 是与处理器管理相关的硬件虚拟化技术[6]。在VT-x 的支持下,KVM 中的每个虚拟机可具有多个虚拟处理器VCPU,每个VCPU 对应一个KQEMU 的线程,这个KQEMU 线程代表了KVM 虚拟机的运行。没有硬件支持的纯QEMU 虚拟机和利用硬件支持实现虚拟化的KVM 虚拟机的差异也就在这里。为了更加形象地说明KVM 和KQEMU 间的关系,本文称它为KVM 线程,而将创建客户机的应用程序KQEMU 称为KQEMU 进程。KQEMU 应用程序在创建或者说在加载一个Guest OS 后,就转换为KVM 线程运行。VCPU 的创建、初始化、运行以及退出处理都在KVM 线程上下文中进行,需要Kernel、User 和Guest 三种模式相互配合,其工作模型如图2 所示:
图2 KVM 工作模型
从图2 可看出,KVM 线程以ioctl 的方式与KVM内核模块间进行交互,指示KVM 内核模块进行VCPU的创建和初始化等操作,而KVM 内核模块与客户机之间通过VM Exit 和VM entry 操作进行切换。初始化工作完成之后,KVM 线程以ioctl 的方式向KVM 内核模块发出运行VCPU 的指示,后者执行虚拟机进入操作(VM entry),将处理器由Kernel 模式切换到Guest 模式,转而运行客户机。但此时仍处于KVM 线程上下文中,且正在执行ioctl 系统调用的kernel 模式处理程序。
客户机在运行过程中,如发生异常或外部中断等事件,或执行I/O 操作,可能导致虚拟机退出操作(VMexit),将处理器状态由Guest 模式切换回Kernel 模式。KVM内核模块检查发生VM exit 的原因,如果VM exit由I/O 操作导致,则执行系统调用返回操作,将I/O操作交给处于User 模式的KQEMU 进程来处理,这时KQEMU会创建一个新的KQEMU线程来完成这些I/O处理,之后再次执行ioctl,指示KVM 将处理器切换到Guest 模式,恢复客户机的运行;如果VM exit 由其它原因导致,则由KVM 内核模块负责处理,并在处理后切换处理器到Guest 模式,恢复客户机的运行。
由以上分析可知,KVM 虚拟化技术中物理CPU核的隔离实现,与KQEMU 应用程序、KVM 线程、异步IO 事件处理这三方面有着密切的联系。
3 虚拟机进程隔离实现
3.1 隔离方案设计
在KVM 虚拟机运行的过程中,与虚拟机处理器紧密相关的重要数据结构VMCS保存在内存中,包含了虚拟CPU 的相关寄存器的内容和虚拟CPU 相关的控制信息,每个VMCS对应一个虚拟CPU。但VMCS具有“迁移性”,使用时需要与物理CPU 绑定。例如,某个VMCS 先和物理CPU0 绑定,并在某个时刻解除绑定关系,下一个时刻可能会重新绑定到物理CPU1上。在任意给定时刻,VMCS 与物理CPU 是一对一的绑定关系,即一个VMCS 只能与一个物理CPU 绑定。
因此,多核条件下要实现Guest OS 在一个虚拟的单核平台上运行,就需要考虑KQEMU 应用程序、KVM 线程、异步IO 事件处理与CPU 的绑定关系。利用CPU 的亲和性(Affinity),通过设置这三方面的Affinity 属性,可以将Guest OS 进程绑定到指定的核上运行,从而实现虚拟的单核平台。例如,在创建虚拟机时将两个Guest OS 进程绑定到指定的CPU 核上,使其在整个运行期间不发生迁移,如图3 所示:
图3 客户操作系统与CPU 核的绑定
根据KVM 原理和机制的分析,可以通过两个方案实现绑定操作:
方案一:直接通过内核函数设置Guest OS 进程的属性,实现Guest OS 保持运行在指定的核上。通过编写脚本文件,使创建虚拟机和绑定两项操作自动完成。
方案二:修改、优化KQEMU 源代码,生成特定的KVM 虚拟机。在创建客户机的时候实现绑定,使客户机只能在指定核上的运行,不发生迁移。
从两个方案的设计可知,方案一的主要是从KQEMU应用程序的应用出发的,它的实现必然要用到文件的读写和脚本的绑定,以及虚拟机管理器启动脚本的修改。方案二是基于Qemu 源代码的修改,绑定时机明显早于方案一,实现过程也更简单明了。除此之外,方案一从理论上来说,对有异步IO 时才产生的aio 线程的绑定可能出现问题,所以本文最终选择方案二。
3.2 处理器隔离的实现方法
Linux 的线程在核内是以轻量级进程的形式存在的,而实现是在核外。它拥有独立的进程表项,其创建、删除等操作都是在核外POSIX thread 库中进行。与fork() 调用创建一个进程的方法不同,pthread_create()创建的线程并不具备与主线程同样的执行序列,而是使其运行start_routine()函数。因此,用fork 创建的父子进程之间的Affinity 具有继承性,而调用pthread_create()创建的父子进程之间则没有这种继承性,KQEMU 和KVM 之间则是后者的情况。
因此,仅通过设置KQEMU 的Affinity 属性不能实现KVM 虚拟机处理器的隔离。需分为两部分处理:
①从启动QEMU 的命令获取cpuid 参数。这需要对KQEMU 源代码进行修改,增加-cpuid 的命令选项,完成对参数的解析以及相关的绑定操作。主要涉及KQEMUOption、KQEMU_options 等几个选项变量。
②根据解析获得的cpuid 参数,对KQEMU 应用进程、KVM 线程、异步IO 事件处理线程运用Linux 内核的Affinity 机制进行绑定,实现对处理器的隔离。图4 是以双核处理器为例实现KVM虚拟机绑定的主要过程。
图4 KVM 虚拟机进程绑定实现过程
4 实验结果与分析
由设计思路的分析可知,对方案二实现方法需要验证的是客户机的创建、客户机的运行,以及客户机的异步IO 事件处理。本实验中使用的测试平台是:处理器是Pentium(R) Dual-Core CPU E5300 2.60GHz,内存为DDR2-800 2G , 操作系统内核版本是Linux-2.6.33.2 。GuestOS 运行测试程序是计算Fibonacci 前35 项和,每计算一次休眠15 毫秒。
执行命令qemu-system-x86_64 Guestos.img –m512–cpuid 1,在启动Guest OS 时指定创建Guest OS进程的处理器参数cpuid,使创建客户机的进程在指定的核1 运行。用top 命令的p 和H 参数,观察KVM虚拟机运行时的进程号和线程号。
t1 时刻(19:33:34),KQEMU 进程号为3905,KVM线程号为3906,异步IO 事件处理线程号为3910,如图5 所示:
图5 t1 时刻KVM 虚拟机进程运行状态
t2 时刻(20:43:20),KQEMU 进程号为3905,KVM线程号为3906,异步IO 事件处理线程号为4212,如图6 所示。此时图4 中线程号为3910 的aio 线程消失,动态产生aio 线程4212。
图6 t2 时刻KVM 虚拟机进程运行状态
根据Linux 内核的PID 命名规则可知,PID 逐渐递增,aio 线程的产生是一个动态过程,根据Guest OS的需要而产生。从而进一步证实,如果用采用方案一,则难以实现aio线程的绑定。
经过长时间的实验观察,虽然运行Guest OS 时CPU 核1 的利用率达到94.7%左右,KVM 虚拟机始终保持在指定的核1 运行,即使核0 十分空闲,仍不会发生迁移。可以通过taskset 命令查看这三个进程的Affinity 值,得到进一步的验证,如图7 所示。图中3905 , 3906 , 4212 进程的Affinity 值为2 ( 即0x00000010),表示相应进程或线程运行在核1 上。
图7 用taskset 命令查看虚拟机进程的Affinity 值
5 结论
本文通过对KVM 虚拟机的绑定,实现了KVM 虚拟机处理器核之间的隔离,使KVM 虚拟机在指定的物理CPU 核上运行,不发生核间的迁移,从而达到物理CPU 资源的指定使用。当运行多个Guest OS 时,只需在运行时指定CPU 参数,即可让各个Guest OS始终运行在指定的核上,进而能够充分有效地利用计算机硬件资源。
核心关注:拓步ERP系统平台是覆盖了众多的业务领域、行业应用,蕴涵了丰富的ERP管理思想,集成了ERP软件业务管理理念,功能涉及供应链、成本、制造、CRM、HR等众多业务领域的管理,全面涵盖了企业关注ERP管理系统的核心领域,是众多中小企业信息化建设首选的ERP管理软件信赖品牌。
转载请注明出处:拓步ERP资讯网http://www.toberp.com/
本文标题:KVM虚拟化技术中处理器隔离的实现