调度

 “启动太阳轨道计算软件‘Three-Body l.0’!”牛顿声嘶力竭地发令,“启动计算主控!加载差分模块!加载有限元模块!加载谱方法模块……调入初始条件参数!计算启动!!”

本文将对linux中进程调度相关知识进行介绍。

准备知识

进程分类

根据进程运行状态,可以将进程分为两种:

  • IO密集型:吞吐量大,CPU占用率低,例如网络通信中的监听进程
  • CPU密集型:吞吐量少,CPU占用率高,例如编译器进程

由于进程的不同表现,我们实际上会采取不同的策略,IO密集型往往是交互进程,响应时间敏感,属于高优先级;而CPU密集型,例如编译器进程,响应要求不高,因此属于低优先级。对于时间响应敏感的,我们要奖励,占用CPU资源多的,我们要惩罚。

graph LR
    start((start))
    ioTask[IO密集型]
    cpuTask[CPU密集型]
    bonus[奖励, 提高优先级]
    panish[惩罚, 降低优先级]

    start --> ioTask
    start --> cpuTask
    ioTask --> bonus
    cpuTask --> panish

进程优先级

根据进程重要性,可以将进程分为:

  • 实时进程
  • 普通进程

实时进程相对重要,需要保证CPU占用优先级,普通进程不需额外照顾,linux中影响优先级的两个因素:Nice值(谦让值)和priority(权重),优先级和权重的关系如下:

  • 实时进程PR值范围是0~99,数值越大被调度优先级越高

  • 普通进程PR值范围是100~139,数值越小被调度优先级越高

  • Nice值范围是-20~19,并不是优先级但影响PR值,一般作用在普通进程上

图片名称

PR值由内核决定,而用户态可以修改Nice值,干预PR值

Nice值为谦让值,如果为0,表示不干预内核,听天由命;如果为负值,表示用户态干预提高优先级,将机会留给自己;如果为正,表示降低优先级,将机会留给别人。下面这张图很形象:

图片名称

抢占与非抢占

说完了任务类型,我们再来聊聊调度类型,根据进程在占用CPU时,使用权是否被剥夺,我们可以将调度分为如下两种:

  • 非抢占式:进程任务一旦占据CPU,只有当前任务完成或等待IO时释放CPU,不能被其他进程夺走
  • 抢占式:任务占用CPU期间可以被抢占,由操作系统调度器决定下一个占用CPU的任务

Linux采用抢占式,CPU利用率和响应时间较好,但是增加了开销

调度器设计指标

设计调度器的时候,需要考虑两个指标:

  • 周转时间:任务从开始排队等待CPU资源到任务完成的时间差,即等待+执行的时间
  • 响应时间:任务从开始排队到开始使用CPU的时间差,即等待时间

综合来说,有如下几点设计经验:

实时进程优先调度,普通进程优先级低于实时进程

IO密集型要频繁调度,分配较短时间片,少食多餐

CPU密集型要稍微惩罚,分配长时间片,多食少餐

调度算法

以下介绍几种常见的调度算法,记住:没有银弹

FIFO调度

经典的先来先服务

参考文献

0%