KVM 入门 (一)
最近用一些零碎的时间学习KVM,算算大概也快有一个月了吧,进度还是很缓慢的,感觉该写一些类似读书笔记的东西了。欢迎大家来讨论。 KVM 即 Kernel Based Virtual Machine, 是一个内核模块,使用它需要CPU支持虚拟化。加载KVM模块后,系统中会有一个 /dev/kvm 设备,这个设备提供 ioctl 和 mmap操作。 目前,KVM还必须和修改过的Qemu配合起来使用(这样说是不准确的,因为已经有一个叫 native kvm tool的东东了),KVM 使用Qemu做I/O模拟,虽然Qemu也提供CPU的模拟,但是KVM没有使用,也许这正是KVM+Qemu比单纯用Qemu进行虚拟化性能高的原因吧。 运行在Qemu中的虚拟机被称为Guest,运行Qemu的物理机称为Host, 每一个guest是host上的一个进程,guest的每一个cpu对应进程中的一个线程。 Qemu和KVM之间通过ioctl进行交互,KVM和guest之间通过VM Entry和VM Exit进行切换。 那么什么时候会发生VM Entry和VM Exit呢? 先从虚拟化这个概念说起,其实通常的进程/线程也是一种虚拟化。Intel把CPU的优先级分了4层,ring0完整的暴露了CPU的各个接口,运行在ring0的操作系统可以任意使用CPU提供的所有功能,相比之下,运行在ring3的应用程序只能看到较少的CPU接口。 在这种情况下,操作系统担任的角色就是类似VMM(Virtual Machine Monitor)。运行在ring3的应用程序,自以为自己掌握所有的计算机资源,比如CPU资源,4GB的内存等等。众多傻乎乎的应用程序(用户态进程)在自己的虚拟世界里玩的不亦乐乎,而操作系统默默的在背后处理各个进程CPU相关的数据的保存和恢复,比如修改cr3寄存器,修改页表等等。 所以,操作系统完成了对ring3环境下的CPU的虚拟化,而KVM则是实现了一个完整的CPU虚拟化(所以这种类型的虚拟化,能运行不经任过何修改操作系统)。 kvm是一个内核模块,用kvm虚拟化技术创建的虚拟机,如果guest OS 执行的是与访问全局资源无关的指令,那么这些指令是直接运行在物理CPU上的; 当执行到了访问全局资源的指令,比如产生缺页错误,或者设备I/O,则guest OS产生VM Exit退出到KVM中,然后KVM再根据退出的原因,决定是由自己来处理还是交给Qemu。 当发生VM Entry和VM Exit 时必须要有一个结构体来保存当前CPU的上下文,这个结构就是VMCS (Virtual Machine Control Structure),而前面提到的,使用KVM必须要有CPU硬件上的支持,指的就是CPU硬件必须提供一种功能,能自动根据VMCS的内容完成VM和VMM之间的状态切换。 从原博客拷贝的评论 Davelv: 写的不错,让我这种没研究KVM技术的人都看懂了。 不过有一点比较容易让人疑惑,在这里没有说清楚qemu是什么。 qemu在这里就是qemu-kvm这个修改版,他是一个单独的程序,运行起来是一个进程。 就是你说的使用KVM技术的qemu,这个进程的一些IO操作是像原始的qemu一样做模拟,但是和处理机相关模拟则会调用的kvm内核模块的功能(而不是像旧的qemu一样全部自己模拟)。kvm内核模块是一个运行在ring0的系统模块(驱动)本身没有独立的进程,依附于系统内核存在,作为操作系统(ring0层)的一部分 给应用程序(ring3层)如qemu-kvm相应支持。