KVM VCPU线程调度问题的讨论
2017-11-15
今天闲着没有突然想了想VCPU线程调度的问题,具体描述如下:
当代表VCPU的线程获得控制权后,首先会通过KVM接口进入到内核,从内核进入到非根模式,那么此时站在全局调度器的点上,这并不算做线程的时间,这种情况下调度器还能正常调度VCPU线程吗?
通过查看intel手册,分析相关时钟中断的源代码,目前理解如下:
基本知识:
CPU的VMX模式分为root模式和non root模式,二者的0-3环是正交的,即在root模式下有ring0~ring3,在non root模式下也有ring 0到ring3,一个VCPU线程得到运行,通过KVM接口进入到内核,最终需要从root模式进入到non root模式,进入non root模式后就是虚拟机运行的阶段了。虚拟机有自己的内核层和用户层,即ring0-ring3。
按照当前Linux下的CFS调度器为例,基于虚拟运行时间来调度进程,而虚拟运行时间的统计本质上还是基于时钟中断。时钟中断处理程序中会分析当前CPU处于ring0 还是ring3(不区分root和non root),继而更新进程时间统计量。之前听人说进程在内核中的时间是不算做调度参考时间的,但是根据代码来看,时钟中断时不管是处理用户态还是内核态,最终都会增加对应进程的虚拟运行时间,这点如有仁兄明白还请告知。而在中断会返回的时候,我们知道在抢占内核下,会增加一个调度时机,此时如果有更加紧迫的进程需要执行,则进行内核抢占。如果返回用户空间,则正常进行调度的检查。
回到开始我们提出的问题,假如一个虚拟机正在运行,此时时钟中断到来,那么CPU 在保存现场后,继而去执行中断处理程序,其中就会统计当前进程(必然是VCPU线程)的时间信息,并会更新VCPU线程的虚拟运行时间,如果运行时间到了则设置重调度位,处理完成后返回。如果之前虚拟机位于内核模式(non root 下的内核模式)且支持内核抢占,则会触发调度器进行调度;如果虚拟机位于用户模式,则会直接触发调度。所以从这里看,HOST上调度器的运行和VMX模式并没有本质联系。而虚拟机内部进程的调度就比较容易理解了,和传统进程调度没有区别,虽然INTEL手册严格规定了non root模式下不允许任务切换吗,但是其实针对使用TSS来说的,而现实情况下,不管是windows还是Linux 都没有使用TSS做任务切换,故实际上虚拟机内部进程切换还是在non root 模式下进行的(至少目前我是这么认为的)
以马内利
参考:
intel 手册
Linux内核源码