概念

内核在内存中保存了每个进程的唯一描述,并通过若干接口与其他进程连接起来。调度器的主要目的是为了,在进程之间共享CPU时间,以达到一种程序都在并发执行的假相。

涉及的东西

  1. 调度策略:内核必须提供一种方法,尽可能公平的为各个进程之间分配CPU时间片,同时又要兼顾不同任务的优先级。
  2. 上下文切换:调度在各个进程之间切换时,需要保存前一个进程的状态,待下次循环再次执行该进程时恢复其状态,这就是上下文切换。

Linux 中的调度器实现

调度器的一般原理是,按所能分配的计算额能力,尽可能地保证最大的公平性。Linux的调度器一个很好的特性是,它不需要时间片概念(传统的时间片)。所有的可运行进程都按照时间在一个红黑树中排序,所谓时间就是等待时间。等待最长的进程排在最左侧,则下一次调度器会优先考虑让该进程执行。

调度器需要考虑的点

  1. 进程的不同优先级,更重要的进程必须比次要进程得到更多的CPU时间份额。
  2. 进程切换不能太频繁,因为上下文切换是有开销的,因减少在进程切换的开销,让CPU的能更多的运用在计算上。
  3. 两次相邻的任务切换,不能时间过长,否则会积累比较大的不公平值。

调度器的数据结构

4.png

有两种方式激活调度。一种是,直接的,比如进程打算睡眠或其他原因;另一种是周期性的,以固定的频率运行,不时的检测是否有必要进行进程切换。

struct task_struct {
...
  int prio, static_prio, normal_prio;
  unsigned int rt_priority;
  struct list_head run_list;
  const struct sched_class *sched_class;
  struct sched_entity se;
  unsigned int policy;
  cpumask_t cpus_allowed;
  unsigned int time_slice;
...

rt_priority: 表示实时进程的优先级。0~99,值越大优先级越高。
sched_class: 调度器种类
policy: 调度策略。

  • SCHED_NORMAL: 普通进程
  • SCHED_BATCH/SCHED_IDLE 次要进程,使用完全公平调度器处理。
  • SCHED_BATCH 用于非交互的,密集的批处理进程。
  • SCHED_RR/SCHED_FIFO 用于实现软实时进程。SCHED_RR 是循环,SCHE_FIFO 是先进先出。
    cpu_allowed: 指定进程在哪个CPU上运行

进程处理优先级

  1. 优先级的内核表示
    在用户空间可以使用nice命令设置进程的静态优先级。-20~+19。值越小,优先级越高。
  2. 计算优先级
    动态优先级>普通优先级>静态优先级
  3. 计算负荷权重
    进程每降低一个nice值,则多获得10%的CPU时间。

核心调度器

  1. 周期性调度器
    在系统活动时,内核会按照频率自动调用该调度器对进程进行分配。
  2. 主调度器
    当要将CPU分配给与当前活动不同的另一个进程,会使用主调度器。
  3. 与fork的交互
    会使用父进程的普通优先级作为子进程的动态优先级,内核会确保父进程的优先级的临时提高不会被子进程集成。
Last modification:July 16, 2022
If you think my article is useful to you, please feel free to appreciate