LKD(Linux内核设计与实现) Chapter 4 Process Scheduling

作为一个多任务抢占式操作系统,Linux调度器需要决定:

  • 在当下选择哪个任务运行
  • 是否抢占正在运行的任务

这是个相当复杂的问题,不同的系统有不同的偏向性。比如一些系统偏向实时性的任务调度,要求任务在执行时间上有确定性;另外一些系统则偏向吞吐量,希望能执行更多任务,最大化CPU使用率;还有一些系统注重交互性,比如桌面系统。

对此,单一的调度策略显然不能满足所有偏向性。Linux支持不同调度策略:

  • SCHED_FIFO (软实时,基于优先级)
  • SCHED_RR(软实时,基于优先级+时间片)
  • SCHED_OTHER/SCHED_NORMAL (非实时,交互性任务和吞吐性任务并重)
  • SCHED_BATCH ( 非实时,偏向批处理任务,出现于2.6.16)
  • SCHED_IDLE (非实时,偏向驻留后台的低调任务,出现于2.6.23)

SCHED_FIFO/SCHED_RR

Linux为了优先满足实时性任务,设计了两个高优先级的调度策略SCHED_FIFO和SCHED_RR,这两个调度策略下的任务可以抢占其他策略下的任务。

SCHED_FIFO和SCHED_RR采用静态优先级机制,高优先级的任务抢占执行。不同的地方是SCHED_FIFO需要高优先级的任务主动放弃执行之后其他任务才有机会执行;而SCHED_RR策略多一个时间片的概念,当一个任务用完时间片之后,其他同优先级的任务可以有机会执行。

相应的代码在kernel/sched/rt.c

SCHED_OTHER/SCHED_NORMAL

SCHED_OTHER,顾名思义是用来调度除了实时策略之外的任务,即任务的静态优先级为0。作为桌面系统或者服务器系统的,大部分的任务是运行在这个调度策略之下。

这个策略要求调度器既有交互性又有吞吐量,要兼顾两种极端类型的任务,一是I/O-Bound的,另一种是Processor-Bound的。前一种任务大部分时间都在等待I/O操作,但是在唤起时需要更快地被调度到,也就是说这种任务希望延迟较低;后一种任务则希望更多地占据CPU时间,不被打断。

SCHED_OTHER的任务具有动态优先级,调度器根据任务的CPU使用情况来调整动态优先级。任务的动态优先级受相应的nice值影响,nice值范围从-20到+19,值越大优先级越低。

相应的代码在kernel/sched/fair.c

SCHED_BATCH

这个策略是2.6.16新增的,和SCHED_OTHER一样静态优先级为0,用来调度侧重吞吐量的任务。

相应的代码在kernel/sched/fair.c

SCHED_IDLE

这个策略是2.6.23新增的,和SCHED_OTHER一样静态优先级为0,用来调度CPU需求极低的任务。

相应的代码在kernel/sched/idel.c

相应的系统调用

  • sched_setscheduler, sched_getscheduler – set and get scheduling policy/parameters (设置调度策略)
  • sched_get_priority_max, sched_get_priority_min  – get static priority range(设置静态优先级)
  • sched_setparam, sched_getparam – set and get scheduling parameters (
  • nice – change process priority (设置影响动态优先级的nice值)
  • getpriority, setpriority – get/set program scheduling priority (设置影响动态优先级的nice值,功能比nice强大)
  • sched_rr_get_interval – get the SCHED_RR interval for the named process (设置SCHED_RR策略的时间片长度)

 

  • 文章中涉及的任何代码都参考Linux v4.4
  • man shec(7)