cpu_shares是如何影响这个cpu时间片的,这就需要去看一下linux进程调度原理。
Linux 调度器
内核默认提供了5个调度器,Linux内核使用struct sched_class来对调度器进行抽象∶
- Stop调度器,stop_sched class∶优先级最高的调度类,可以抢占其他所有进程,不能被其他进程抢占
- Deadline调度器, dl sched class∶使用红黑树,把进程按照绝对截止期限进行排序,选择最小进程进行调度运行
- RT调度器,rt_sched_class∶实时调度器,为每个优先级维护一个队列
- CFS调度器,cfs sched class∶完全公平调度器,采用完全公平调度算法,引入虚拟运行时间概念
- IDLE-Task调度器,idle sched class∶空闲调度器,每个CPU都会有一个idle线程,当没有其他进程可以调度时,调度运行idle线程;
linux里面提供了多个进程调度器,最高优先级的是RT,就是real time的调度器,这个调度器基本上是轮训的,如果多个进程是使用RT调度器去调度,那么他就会轮流的去调度,这样的话保证其时效性。
次优的是CFS调度器,一般普通的用户进程都是使用CFS调度器,这个调度器是我们平时遇到最多的一种调度器。
CFS调度器
- CFS是Completely Fair Scheduler简称,即完全公平调度器
- CFS实现的主要思想是维护为任务提供处理器时间方面的平衡,这意味着应给进程分配相当数量的处理器。
- 分给某个任务的时间失去平衡时,应给失去平衡的任务分配时间,让其执行。
- CFS通过虚拟运行时间(vruntime)来实现平衡,维护提供给某个任务的时间量。
vruntime =实际运行时间*1024/进程权重
- 进程按照各自不同的速率在物理时钟节拍内前进,优先级高则权重大,其虚拟时钟比真实时钟跑得慢,但获得比较多的运行时间
一个进程的权重越大,那么它的运行时间越长,虚拟时钟跑的越慢。
Vruntime红黑树
CFS调度器没有将进程维护在运行队列中,而是维护了一个以虚拟运行时间为顺序的红黑树。 红黑树的主要特点有∶
- 自平衡,树上没有一条路径会比其他路径长出俩倍。(基本上是维持均等路径的,左边和右边的树基本平衡,可能相差那么几个节点,但是基本上是平衡的)
- O(log n)时间复杂度,能够在树上进行快速高效地插入或删除进程。(平衡排序树)
那么linux kernel如何利用这个红黑树呢?它将vruntime最小的进程放在左边,vruntime最大的进程放在右边,然后在做调度的时候会从最左边取出这个最小值,也就是谁的vruntime到了,它就会去运行谁。
CFS进程调度
- 在时钟周期开始时,调度器调用_schedule()函数来开始调度的运行。
- schedule()函数调用pick_next_task()让进程调度器从就绪队列中选择一个最合适的进程next,即红黑树最左边的节点(vruntime最小的那个节点)。
- 通过context_switch()切换到新的地址空间,从而保证next进程运行。(调度到这个进程就需要做上下文的切换)
- 在时钟周期结束时,调度器调用entity_tick()函数来更新进程负载、进程状态以及vruntime(当前vruntime+该时钟周期内运行的时间)。(时钟周期结束之后需要去更新这个进程,也就是将这个进程的vruntime更新一下,因为有些进程执行了,有些进程没有执行,所以vruntime会去做个顺序的调整,红黑树就会去做插入,反转,重新排序,会将一个更加紧迫的进程丢到最左边,每次进程调度的时候,它永远从最左边取vruntime值最小的这个进程取调度)
上面是调度的优先级
进程优先级高的进程,它的vruntime消耗的慢,也就是它可以占用越多的时间,通过这样的话就可以和cpu_shares本身产生一个关联,也就是cpu_shares越大的这种进程,它能够占用的cpu的时间越长,
- 最后,将该进程的虚拟时间与就绪队列红黑树中最左边的调度实体的虚拟时间做比较,如果小于坐左边的时间,则不用触发调度,继续调度当前调度实体。