调度策略和调度类
- 停机调度类是优先级最高的调度类,停机进程(stop-task)是优先级最高的进程,可以抢占所有其他进程,其他进程不可以抢占停机进程。停机(stop是指stopmachine)的意思是使处理器停下来,做更紧急的事情。目前只有迁移线程属于停机调度类,每个处理器有一个迁移线程(名称是migration/CPU_ID)。
- 限期调度类使用最早期限优先算法,使用红黑树(一种平衡的二叉树)把进程按照绝对截止期限从小到大排序,每次调度时选择绝对截止期限最小的进程。如果限期进程用完了它的运行时间,它将让出处理器,并且把它从运行队列中删除。在下一个周期的开始,重新把它添加到运行队列中。
- 实时调度类为每个调度优先级维护一个队列,每一个优先级队对应一个bitmap位,位图bitmap用来快速查找第一个非空队列。数组queue的下标是实时进程的调度优先级,下标越小,优先级越高。每次调度,先找到优先级最高的第一个非空队列,然后从队列中选择第一个进程。
- 使用先进先出调度策略的进程没有时间片,如果没有优先级更高的进程,并且它不主动让出处理器,那么它将一直霸占处理器。
- 使用轮流调度策略的进程有时间片,用完时间片以后,进程加入队列的尾部。默认的时间片是5毫秒,可以通过文件“/proc/sys/kernel/sched_ms”修改时间片。
- 公平调度类使用完全公平调度算法。完全公平调度算法引入了虚拟运行时间的概念:虚拟运行时间=实际运行时间×nice0对应的权重/进程的权重。
- nice0对应的权重是1024,nicen-1的权重大约是nicen权重的1.25倍。
- 完全公平调度算法使用红黑树把进程按虚拟运行时间从小到大排序,每次调度时选择虚拟运行时间最小的进程。显然,进程的静态优先级越高,权重越大,在实际运行时间相同的情况下,虚拟运行时间越短,进程累计的虚拟运行时间增加得越慢,在红黑树中向右移动的速度越慢,被调度器选中的机会越大,被分配的运行时间相对越多。
- 调度周期:在某个时间长度可以保证运行队列中的每个进程至少运行一次,我们把这个时间长度称为调度周期。
- 调度最小粒度:为了防止进程切换太频繁,进程被调度后应该至少运行一小段时间,我们把这个时间长度称为调度最小粒度。默认值是0.75毫秒,可以通过文件“/proc/sys/kernel/sched_min_granularity_ns”调整。如果运行队列中的进程数量大于8,那么调度周期等于调度最小粒度乘以进程数量,否则调度周期是6毫秒。
- 进程的时间片=(调度周期×进程的权重/运行队列中所有进程的权重总和)
- 空闲调度类
每个处理器上有一个空闲线程,即0号线程。空闲调度类的优先级最低,仅当没有其他进程可以调度的时候,才会调度空闲线程。
CFS调度模型
主动调度和被动调度
- 主动调度:进程自愿性主动调用函数sched_yield函数;进程非自愿性主动调度,进程由于等待资源等原因发生了阻塞
- 被动调度:
- 触发点:时钟中断 scheduler_tick,进程唤醒 wake_up_process;设置当前进程current的NEED_RESCHED flag
- 执行点:系统调用完成返回用户空间;中断完成返回用户空间;中断完成返回内核空间;禁用抢占临界区结束。
进程切换逻辑
优先级与权重计算
nice值直接转为static_prio,由static_prio计算出se的load->weight ;用户设置的nice值为[-20,19],按比例转换为100~139,static_prio = nice + 120
_do_fork->copy_process->sched_fork->set_load_weight
用户所创建的进程 nice 值为 0,对应调度实体的 weight 值为 1024,相差一个 nice 值,对应的 weight 值之间的差别大约为 1.25 倍。