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)