Process Scheduling [LKD 04]

前面一章讲的是process,这一章讲process schedule。

进程调度的主要工作就两个:选哪个process开始执行,以及让它执行多长时间。

Multitasking


linux是多任务操作系统,如果有SMP,就有多个process同时在执行,如果是单核,就只有一个process执行。多任务操作系统分为两类:cooperative multitasking和preemptive multitasking。大多数多任务系统都是preemptive multitasking,也就是抢占式的多任务操作系统。当一个process执行了一段时间,scheduler可能会停止它的运行,转而执行另外的process,这个过程就是抢占,而process之前执行的那段时间,就是timeslice,多数系统上,这个timeslice是动态分配的,根据process任务种类或者系统配置来设置。

Linux’s Process Scheduler


linux kernel中使用了一种O(1)的scheduler,也就是时间复杂度是常数,这种调度算法就是CFS(Completely Fair Scheduler)。

Policy


策略就是scheduler的实现,比如挑选哪个process运行多久。scheduler的实现策略会显著影响系统的performance,因此尤其重要。

I/O-Bound Versus Processor-Bound Processes

通常来说,process可以分为两类:I/O-bound和processor-bound。前者指的是大部分时间是在等待I/O的process,后者指的是大部分时间都是在使用CPU执行code。

I/O-bound process每次只执行一小段CPU时间,剩下的时间就是等待I/O,跟UI相关的process就是典型的I/O-bound的process,因为它大部分时间都是在等待鼠标或者键盘的事件。

processor-bound process则不一样,它会一直使用CPU执行code,直到它被抢占。scheduler对这种process,就会很少调度,但是一旦调度,就是让它执行比较长的时间。典型的processor-bound process,比如无限循环,或者数学计算程序等。

但是现实中的process,基本上不会有这么明显的划分,他们可能既有执行I/O的需求,也有使用CPU做大量运算的时候。但无论如何,scheduler都要尽量实现两个目标:尽可能快的CPU反应时间(low latency,低延迟),尽可能多的让CPU干活(high throughput,高吞吐)。这两个目标本身是互斥的,因此scheduler就需要复杂的算法尽可能的实现这两个目标。Linux,或者说Unix,都更偏向于调度I/O-bound process,以获得更快的系统反应时间(从UI用户角度)。

Process Priority

一个直观的process调度,就是就进程优先级来做,通过对所有的process根据价值和执行的时间排个序,从而确定优先级。在scheduler调度时,优先调度高优先级的process,而相同优先级的就使用RR(round-robin)来选择。

而Linux kernel有两种独立的优先级算法。第一个是根据nice值来算优先级,每个process都会有一个nice值,default是0,范围可以是-20 - +19. nice值越高,优先级越低。nice值这种优先级的算法在所有的Unix系统中都有使用,但是不同的系统可能有自己的实现算法,比如使用nice值计算process的timeslice就是不一样的。第二个是real-time proirity,即运行时优先级。这个值也是可以配置的,但是一般是0-99之间。和nice值相反,这个priority越高说明优先级越高,一个real-time的process就比normal process有更高的real-time priority值。nice值优先级和real-time优先级是正交的,也就说他们同时被使用。通过这个命令可以看到process的real-time priority(RTPRIO这一列):

ps -eo state,uid,pid,ppid,rtprio,time,comm

Timeslice

timeslice的值,决定了这个process在执行多久之后会被抢占。schedule要能够有一个合理的timeslice,否则会影响schedule的质量,如果某个process的timeslice过大,执行的时间过长,那么其他的process就会等待更久,如果是UI的proces被block,用户明显会觉得performance很差,这就会导致high latency;如果设置的timeslice过小,process执行的时间过短,那么很多时间可能就花费在了context switch上,造成很低的吞吐率,low throughput。另外,考虑到之前提高的I/O-bound和process-bound process,前者需要更少的timeslice,后者需要更多的timeslice,这些scheduler都需要考虑到。

timeslice如果设置的过长,那么系统整体的performance会很低,因此绝大多数操作系统都会把default timeslice设置的很低,比如10ms。但是Linux kernel并不会设置这样一个default timeslice,它会在运行时动态计算timeslice,并且这个timeslice也并不是时间片,而是CPU的比例。process的CPU比例,会根据当前系统的负载,以及process自己的nice值(作为权重),计算而来。nice值低的process占用比较少的CPU比例,nice值高的process占用更多的CPU比例。

Linux kernel是可抢占的,当一个新的process进入了可以运行的状态时,是否抢占当前的process是要根据新的process的优先级,以及它的timeslice来确定的。在Linux的CFS中,如果新的process的CPU比例比当前正在运行的process低,那么就抢占当前的process。

The Scheduling Policy in Action

假设现在有两个process:text editor,和video decoder。前者是明显的I/O-bound,后者是processor-bound。在Linux kernel中,假设只有这两个process,那么每个process的理想的CPU比例是各50%,在两个process实际运行时,因为text editor经常的sleep(等待用户输入),所以它真正使用的CPU比例肯定远远小于50%,而video decoder因为一直在使用CPU,所以它的CPU比例一定是高于50%的。

假如此时text editor被wake up,CFS检查发现它的CPU比例小于50%,那么就认为这个process占用CPU的时间较少,应该尽快调度,所以此时CFS就会决定抢占video decoder,让text editor执行。

The Linux Scheduling Algorithm


Scheduler Classes

Linux kernel的scheduler是分模块化的,针对不同类型的process有不同的调度算法,每种算法被称为schedule class。schedule class中,这些调度算法并存,每种算法只负责调度对应类型的process,并且每个schedule class有自己的优先级,在调度过程中,优先选择优先级高的调度算法。

之前提到的CFS算法就是schedule class中的一种,它针对的process是normal process,Linux中对应的是SCHED_NORMAL。后面讲述的调度算法就是CFS。

Process Scheduling in Unix Systems

这里讲的是别的操作系统的调度算法,涵盖了之前调度的一些问题解释,不看了。

Fair Scheduling

所谓的公平调度,基于这样一个假设:如果有n个process在运行,那么每个process都会得到1/n的运行时间,也就说CPU是理想的CPU,每个进程都完全平等的机会被调度,并且执行同样多的时间。此外,为了保证每个process能执行同样多的时间,调度的时间间隔也应该尽可能小,这样在任意的时间段内,所有的process执行的时间才能一样。

不过这样理想的调度是无法实现的,一方面因为CPU不会逐个执行所有的process,另一方面无限小的调度间隔是达不到的,而且太小的调度间隔,会导致context switch更加频繁,从而浪费了CPU时间。CFS的方式,是给每个需要执行的process分配执行时间,这个时间和当前可以运行的process有关系,而且CFS没有直接使用nice值来计算timeslice,而是把nice作为权重来计算process占用的CPU比例,nice值小的权重就小,nice值大的权重就大。

每个process分配的执行时间,和process本身的权重,以及当前所有可以运行的process的权重之和是成比例的。为了方便计算每个process的timeslice,Linux设置一个targeted latency,这个latency之内,所有的可运行的process会被调度一遍,如果这个值偏小,就会导致每个process的timeslice都会偏小,从而context switch更加频繁,由此就会导致浪费CPU。举个例子,targetd latency是20ms,如果有五个process,每个process就会执行4ms,如果有20个process,每个process就只能执行1ms,也就说要发生20次的context switch࿰

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值