Linux内核之调度器

一、多任务与调度器
  多任务操作系统就是能同时并发的交互执行多个进程的操作系统,在单处理器机器上,这会产生多个进程在同时运行的幻觉。在多处理器机器上,这会使多个进程在不同的处理机上真正同时、并行地运行。无论在单处理器或者多处理器机器上,多任务操作系统都能使多个进程处于堵塞或者睡眠状态,也就是说,实际上不被投入执行,知道工作确实就绪了。这些任务尽管位于内存,但是并不处于可运行的状态。相反,这些进程利用内核阻塞自己,直到某一事件发生了,因此,现代的Linux系统也许有100个进程数据在内存中,但是只有被调度器选择了的进程才会运行处于可运行状态。
  多任务系统可以划分为两类:非抢占式多任务(cooperative multitasking)和抢占式多任务(preemptive multitasking)。像所有Unix的变体和许多其他现代操作系统一样,Linux提供了抢占式的多任务模式。在此模式下,由调度程序来决定什么时候停止一个进程的运行,以便其他进程能够得到执行的机会。这个强制的挂起动作就叫做抢占(preempion)。进程在被抢占之前能够运行的时间是预先设置好的,而且还有一个专门的名字,叫进程的时间片(timeslice)。时间片实际上就是分配给每个可运行进程的处理器时间段。有效管理时间片能使调度程序从系统全局的角度做出调度决定,这样做还可以避免个别进程独占系统的资源。当今众多现代操作系统对程序运行都采用了动态时间片的计算的方式,并且引入了可配置的计算策略。
  调度器可以切换进程的状态(process state),一个Linux进程从被创建到死亡,可能会经过很多种状态,比如执行、暂停、可中断睡眠、不可中断睡眠、退出等。我们可以把Linux下繁多的进程状态,归纳为三种基本状态。

  在这里插入图片描述
  进程创建之后,就自动变成了就绪状态。如果内核把CPU时间分配给了该进程,那么进程就从就绪状态变成了执行状态;在执行状态下,进程执行指令,最为活跃,正在执行的进程可以主动进入阻塞状态,比如这个进程需要将一部分硬盘中的数据读取到内存中,在这段读取时间里,进程不需要使用CPU,可以主动进入阻塞状态,让出CPU;当读取结束时,计算机硬件发出信号,进程再从阻塞状态恢复为就绪状态,进程也可以被迫进入阻塞状态,比如接收到SIGSTOP的信号。
  进程可以被分为I/O消耗性和处理器消耗性。前者指进程的大部分时间用来提交I/O请求或是等待I/O请求。因此,这样的进程经常处于可运行状态,但通常都是运行短短的一会儿,因为它在等待更多的I/O请求时总会被阻塞。相反,处理器耗费性进程把时间大多用在执行代码上了,除非是非抢占了,否则,他们通常都一直不停的运行,因为它们没有太多的I/O需求。
  调度器是CPU时间的管理员,Linux调度器需要负责做两件事情:一件事情是选择某些就绪的进程来执行;另一件事情是打断某些执行中的进程,让它们变回就绪状态,不过,并不是所有的调度器都有第二个功能;调度器在让一个进程变回就绪时,就会立即让另一个就绪的进程开始执行。多个进行接替使用CPU,从而最大效率的利用CPU时间,当然,如果执行中进程主动进入阻塞状态,那么调度器也会选择另一个就绪进程来消费CPU的时间。

二、进程的优先级
  调度算法中最基本的一类就是基于优先级的调度,这是一种根据进程和其对处理器时间的需求来对进程分级的想法,通常的做法是优先级高的进程先运行,低的后运行,相同优先级的进程按轮询方式进程调度。在某些系统中,优先级高的进程使用的时间片也较长。调度程序总是选择时间片未用尽而且优先级最高的进程运行。用户和系统都可以通过设置进程的优先级来影响系统的调度。
  Linux采用了两种不同的优先级范围。第一种用nice值,它的范围是从-20到+19,默认值为0;越大的nice值意味着更低的优先级,nice似乎意味着你对系统中其他进程更"优待"。相比高nice值的进程,低nice值的进程可以获得更多的处理器时间。
  第二种范围是实时优先级,其值是可以配置的,默认情况下它的变化从0到99,与nice值意义相反,越高的实时优先级数值意味着进程优先级越高。任何实时进程的优先级都高于普通的进程,也就是说实时优先级和nice优先级处于互不相交的两个范畴。nice值作为权重将调整进程所使用的处理器时间使用比,具有更高nice值(更低优先级)的进程将被赋予低权重,从而丧失一小部分的处理器使用比;而具有更小nice值(更高优先级)的进程则会被赋予高权重,从而抢得更多的处理器使用比。
  调度器会用两个队列来存放进程,一个队列称为活跃队列,用于存放那些待分配时间片的进程。另一个队列称为过期队列,用于存储那些已经享用过时间片的进程;调度器把时间片从活跃队列调出一个进程,这个进程用尽时间片的CPU时间,就会转移到过期队列中,当活跃队列的所有进程都被执行过后,调度就会把活跃队列和过期队列对调,用同样的方式继续执行这些进程。
  上面的描述中没有考虑优先级,加入优先级之后,情况会变得复杂一些,操作系统会创建140个活跃队列和过期队列,对应优先级0到139的进程,一开始,所有的进程都会放在活跃队列中,然后操作系统会从优先级最高的活跃进程开始依次选择进程来执行,如果两个进程的优先级相同,他们有同等的概率会被选择,执行一次之后,这个进程会被从活跃队列中剔除。如果这个进程在这次时间片中没有彻底完成,它会被加入优先级相同的过期队列中,当140个活跃队列的所有进程都被执行完后,过期队列中将会有很多进程,调度器将对调优先级相同的活跃队列和过期队列继续执行下去。

  在这里插入图片描述

三、CFS(Completely Fair Scheduler)完全公平调度
  从2007年发布的Linux 2.6.23版本起,完全公平调度器成为了Linux的默认调度器,CFS调度器不对进程进程任何形式的估计和猜测。CFS调度器增加了一个虚拟运行时(virtual runtime)的概念,每次一个进程在CPU中被执行了一段时间,就会增加它的虚拟运行时的记录,在每次选择要执行的进程时,不是选择优先级最高的进程,而是选择虚拟运行时最少的进程。完全公共调度用一种叫红黑树的数据结构取代了之前算法复杂度为O(1)的调度器的140个队列,红黑树可以高效的找到虚拟运行最小的进程。
  我们先通过一个例子来看CFS调度器,加入一台运行的计算机中本来有A、B、C、D四个进程,内核记录着每个进程的虚拟运行时;

  在这里插入图片描述
  系统增加一个新的进程E,新创建进程的虚拟运行时不会被设置成0,而会被设置成当前所有进程最小的虚拟运行时,这能保证该进程被较快的执行,在原来的进程中,最小虚拟运行时是进程A的1000纳秒,因此E的初始虚拟运行时会被设置为1000纳秒,新的进程列表如图:
  在这里插入图片描述
  假如调度器需要选择下一个执行的进程,进程A会被选中执行,进程A会执行一个调度器决定的时间片,假如进程A运行了250纳秒,那它的虚拟运行时增加,而其他的进程没有运行,所以虚拟运行时不变,在A消耗完时间片之后,更新的进程列表如图所示:
  在这里插入图片描述
  可以看到,进程A的排序下降到了第三位,下一个将要被执行的进程是进程E,从本质上来看,虚拟运行时代表了该进程已经所消耗了多少CPU时间,如果它消耗的少,那么理应优先获得计算资源;
  按照上述的基本设计理念,CFS调度器能让所有进程公平地使用CPU,听起来,这让进程的优先级变得毫无意义,CFS调度器也考虑也这一点,CFS调度器会根据进程的优先级来计算一个时间片因子。同样是增加250纳秒的虚拟运行时,优先级低的进程实际获得的可能只有200纳秒,而优先级高的进程实际获得可能有300纳秒。这样,优先级高的进程就获得了更多的计算资源。

四、实时调度策略
  Linux提供了两种实时调度策略:SCHED_FIFO和SCHED_RR。而普通的、非实时的调度策略是SCHED_NORMAL。借助调度类的框架,这些实时策略并不被完全公平调度器来管理,而是被一个特殊的实时调度器管理。
  SCHED_FIFO实现了一种简单的、先进先出的调度算法:它不使用时间片,处于可运行状态的SCHED_FIFO级的进程会比任何SCHED_NORMAL级的进程都先得到调度。一旦一个SCHED_FIFO级进程处于可执行状态,就会一直执行,直到它自己受阻塞或者显式地释放处理器为止;它不基于时间片,可以一直执行下去。只有更高优先级的SCHED_FIFO或者SCHED_RR任务才能抢占SCHED_FIFO任务。如果有两个或者更多的同优先级的SCHED_FIFO级进程,它们会轮流执行,但是依然只有在它们愿意让出处理器时才会退出,只要有SCHED_FIFO级进程在执行,其他级别较低的进程就只能等待它变为不可运行状态后才有机会执行;
  SCHED_RR和SCHED_FIFO大体相同,只是SCHED_RR级的进程在耗尽实现分配给它的时间后就不能再继续执行了,也就是说,SCHED_RR是带有时间片的SCHED_FIFO,这是一种实时轮流调度算法,当SCHED_RR任务耗尽它的时间片时,在同一优先级的其他实时进程被轮流调度。时间片只用来重新调度同一优先级的进程。对于SCHED_FIFO进程,高的优先级总是立即抢占低优先级,但低优先级进程绝不能抢占SCHED_RR任务,即使它的时间片被耗尽了;
  这两种实时算法实现的都是静态优先级,内核不为实时进程计算动态优先级。这能保证给定优先级别的实时进程总能抢占优先级比它低的进程。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值