作者:Diting0x
CSysSec注: 本文来自Diting0x的个人博客,主要介绍KVM/QEMU虚拟化基础,对认识KVM与QEMU之间的关系有很大帮助。
转载本文请务必注明,文章出处:《KVM/QEMU虚拟化简介》与作者信息:Diting0x
- 0X01 KVM/Qemu选择与部署
- 0X02 KVM/Qemu原理概览
0X01 KVM/Qemu选择与部署
KVM作为虚拟机监控器VMM,分为两部分,分别是运行于kernel模式的KVM内核模块(kvm-kmod)和运行于user模式的Qemu模块。KVM的具体实现下文会作简单介绍。先来看kvm-kmod部分,linux kernel从2.6版本开始便开始集成了KVM模块,如果你只想简单的使用KVM,只需简单编译和配置内科即可使用KVM的一切特性,这里不作介绍,如果你想基于KVM做开发,还是老老实实去kvm官网下载,自己源码安装吧,在选择KVM版本之前,可以打开任意一个版本例如kvm-kmod-3.8里面的configure文件,可看到以下代码:
这段代码仔细看看,就不难看出kvm-kmod版本的每个数字和kernel版本号都是有关联的,kvm-kmod毕竟是一个内核模块,必须去适应内核,大家如果在安装kvm-kmod时出现kernel is too old 或者kernel is more recent等错误就应该静下来好好看看这段代码了。下载后匹配的kvm-kmod后,安装很简单,只需要执行./configure
make $$ make install
即可
安装之后,有两个模块kvm.ko kvm-intel.ko
便会生成在./kvm/x86文件夹中,执行insmod kvm.ko kvm-intel.ko
或者modprobe kvm.ko kvm-intel.ko
,便成功将kvm模块加载到内核了,
如果期间出现错误,可执行lsmod | grep kvm
看kvm是否成功加载,或执行dmesg | grep kvm
查看具体执行信息。
这里强调,kvm-kmod是内核的一个模块,可随时加载随时删除,因此基于kvm的开发,修改kvm的源码之后,编译与运行起来都很方便。
qemu-kvm是为兼容kvm基于qemu模拟器开发出来的一个分支版本,安装qemu-kvm之前,检查是否有以下依赖包: linux-kernel-headers zlib1g-dev libglib2.0-dev
,如果没有apt-get install
一下。
之后,执行:
./configure --prefix=/usr/local/kvm
make && make install
即可,qemu-kvm便会安装到/usr/local/kvm路径下,安装成功后,会在此路径的/bin文件夹下出现qemu-img, qemu-system-x86_64等二进制文件,自己也可以选择将这些二进制文件拷贝到根目录下的/bin文件夹中,这样在执行这些二进制文件的时候就不用加前缀/usr/local/kvm/bin了。
执行:
/usr/local/kvm/bin/qemu-img create -f qcow2 imgname.img 10G
创建一个qcow2格式的空虚拟机img文件
执行:
/usr/local/kvm/bin/qemu-system-x86_64 -hda imgname.img -m 1024 -vnc :1 -cdrom imgname.iso -boot d
将imgname.iso系统安装到imgname.img中
之后利用xvnc4viewer等vnc软件连接虚拟机完成安装过程,安装完后,执行:
/usr/local/kvm/bin/qemu-system-x86_64 -hda imgname.img -vnc :1 -m 1024 -monitor stdio
登陆到虚拟机。具体细节可自行摸索。
0X02 KVM/Qemu原理概览
说说kvm与qemu的关系,借用实验室某大神给的一张图:
可以看到,这里有三种模式,第一是客户机执行时所处的Guest模式,也就是虚拟化技术VMX中的非Root模式;第二是KVM运行的Kernel模式,即VMX中的Root模式,此时特权级为0;第三是Qemu运行的User模式,处于VMX Root模式中的特权级3.有关VMX技术,以及非Root模式如何通过VM Exit进入到Root模式,Root模式如何通过VM Entry进入到非Root模式,可参考Intel系统编程手册。
简单说说Qemu所在的User模式如何与KVM所在的kernel模式交互,虚拟化中的VT-x技术的支持,使得KVM可以虚拟出多个虚拟处理器VCPU, 而这些VCPU对应每一个Qemu线程,VCPU的创建、初始化、运行以及退出都是在Qemu线程的上下文中进行,这些过程都是通过Qemu向KVM发送一个I/O通道管理函数ioctl来完成,以qemu-kvm-1.1.2为例,qemu-kvm中首先会在./linux-header/linux/kvm.h
注册相应的ioctl,如#define KVM_GET_REGS _IOR(KVMIO, 0x81, struct kvm_regs)
,各参数含义可以具体去了解ioctl的实现方式,之后调用kvm_vcpu_ioctl(env,KVM_GET_REGS,®s)
(有些也会调用kvm_vm_ioctl),KVM-Kmod中也会注册相应的ioctl,之后真正执行时会调用KVM_Kmod的相应函数,一般会在kvm_main.c
文件中定义。如果想自定义自己的函数,需要分别在qemu-kvm与kvm-kmod注册相应的ioctl,只要编号不重复即可,注册后再调用自己定义的函数。
备注:Qemu 线程以 ioctl 的方式向 KVM 内核模块发出指 示,后者执行 VM entry 操作,将处理器由 kernel 模式切换到 Guest 模式,中止宿主机软件, 转而运行客户软件。注意,宿主机软件被中止时,正处于 Qemu 线程上下文,且正在执行 ioctl 系统调用的 kernel 模式处理程序。客户软件在运行过程中,如发生异常或外部中断等事件, 或执行 I/O 操作,可能导致 VM exit,将处理器状态由 Guest 模式切换回 Kernel 模式。KVM 内核模块检查发生 VM exit 的原因,如果 VM exit 由于 I/O 操作导致,则执行系统调用返回操 作,将 I/O 操作交给处于 User 模式的 Qemu 线程来处理,Qemu 线程在处理完 I/O 操作后再 次执行 ioctl,指示 KVM 切换处理器到 Guest 模式,恢复客户软件的运行;如果 VM exit 由于 其它原因导致,则由 KVM 内核模块负责处理,并在处理后切换处理器到 Guest 模式,恢复 客户机的运行。
完
作者@Diting0x
于2016年1月1日West Lafayette, Lawson Computer Science Building.
转载本文请务必注明,文章出处:《KVM/QEMU虚拟化简介》与作者信息:Diting0x