处理器调度

一.CPU调度的相关概念

1.CPU调度

(1).定义

CPU调度的任务是控制、 协调多个进程对CPU的竞争。即按照一定的调度算法,从就绪队列中选择一个进程,然后把CPU的控制权交给被选中的进程。如果就绪队列没有其它的进程,那么系统会安排一个空闲进程(idle 进程)上 CPU 运行。

(2).系统场景

CPU调度所面临的场景:

  • 系统有N 个进程,它们就绪等待上 CPU 运行
  • 而系统有M个 CPU,M $\geq$ 1
  • 操作系统调度模块需要要决策给哪个进程分配哪一个CPU

2.CPU调度要解决的三个问题

  • WHAT:按什么原则选择下一个要执行的进程

    — 调度算法

  • WHEN:何时选择

    — 调度时机

  • HOW:如何让被选中的进程上CPU运行

    — 调度过程(主要内容是:进程的上下文切换)

3.CPU调度的时机

系统运行时,会发生很多的事件。比如说,一些进程的操作:I/O 中断,时间中断。 这些事件发生以后系统要做相应的处理。 这是第二讲的主要内容。

事件发生 → 当前运行的进程暂停运行 → 硬件机制响应 后 → 进入操作系统,处理相应的事件 → 结束处理后:

事件处理完后某些进程的状态发生了变化,也可能创建出了一些新的进程。这就导致了就绪队列的改变,而这就需要进程调度。按照事先预定的算法从就绪队列中重新选择一个进程 ,这就是调度的时机。 即就绪队列的改变引发了重新调度

进程调度的时机有4个:

  • 进程正常终止 或 由于某种错误而终止
  • 新进程创建 或 一个等待进程变成就绪
  • 当一个进程从运行态进入阻塞态
  • 当一个进程从运行态变为就绪态

总而言之什么时候重新调度?

往往是内核对中断,陷入,系统调用等处理之后,返回到用户态,这个时候要重新调度。这就是CPU 调度的时机。

4.CPU调度的过程—进程切换

(1).进程切换的概念

当有一个新的进程被选中之后 ,这个进程可以是刚刚被暂停执行的进程,也可以是一个新的进程。 如果是一个新的进程,那就要发生一个进程切换。

进程切换就指的是一个进程让出CPU,另外一个进程占用CPU的一个过程。

进程切换主要包括两部分工作:

  • 先切换全局页目录,以此来加载一个新的地址空间

    因为新的进程上CPU ,那么它要用自己的地址空间

  • 是切换内核栈和硬件上下文,其中硬件上下文包括了内核执行新进程需要的全部信息,如 CPU相关寄存器

因此,进程切换实际上包括了对原有进程的各种状态的保存,以及对新的进程的状态的恢复,这样一个过程。

(2).上下文切换的具体步骤

例子:如果进程A下CPU,进程B上CPU ,那么进程切换主要做的工作呢?

  1. 保存进程A的上下文环境 (程序计数器、程序状态字、其他寄存器……)

  2. 用新状态和其他相关信息更新进程A的PCB

  3. 把进程A移至合适的队列 (就绪、阻塞……)

  4. 将进程B的状态设置为运行态

  5. 从进程B的PCB中恢复上下文(程序计数器、程 序状态字、其他寄存器……)

做完了这些事情,进程B就上CPU运行, 而进程A的所有信息保存好之后,以后它还可以继续上CPU接着执行。

(3).上下文切换的开销

上下文切换的开销包括两部分:

  • 直接开销:内核完成上下文切换所花费CPU的时间

    这些时间用于:

    • 保存和恢复寄存器
    • 用于切换地址空间 (切换地址空间的指令比较昂贵)
  • 间接开销

    高速缓存(Cache)、缓冲区缓存(BufferCache) 和 TLB快表(Translation Look-aside Buffer)失效

    高速缓存中存放了刚才执行的这些进程中的一些指令和数据, TLB快表中存放了进程的一些页表表项。当新的进程上CPU之后,原来的这些内容都都失效了。还要把新的进程所需要的指令数据,送入高速缓存或者是把新的进程的页表表项送入TLB快表里。这又需要花一些时间,这些都是间接开销。

5.CPU调度算法的设计

从操作系统发展的角度来看调度算法的一些演变:

批处理系统 → 多道程序设计系统 → 批处理与分时的混合系统 → 个人计算机 → 网络服务器

  • 早期的批处理对调度算法的要求不高,也比较简单,那么因为它是一个程序执行完了以后接着执行下一个程序
  • 有了多道程序设计系统之后,多个程序都要想进内存,去上CPU,此时调度算法就要去选择让哪些进程早一点上CPU了
  • 到了批处理与分时系统混合系统中,调度算法既要照顾到前台的进程也要照顾到那些后台的进程,需要合理地安排调度的顺序,让不同的进程都能有机会上CPU执行
  • 个人计算机刚开始时调度算法非常简单,后来慢慢慢慢演化到现在桌面操作系统里头调度算法变得非常复杂
  • 网络服务器由于有多个客户端同时向它提出服务请求,所以要在调度算法上下一些功夫

从用户角度和系统角度对调度算法的要求不一样,下图描述了性能方面的不同要求:

从上图可以看到,用户的角度和系统的角度对于调度算法有不同的要求。 而这些要求有时候是相互矛盾的。 因此在设计调度算法的时候是要在各种因素中折中权衡。

6.调度算法衡量指标

  • 吞吐量 Throughput

    每单位时间完成的进程数目

  • 周转时间TT (Turnaround Time)

    每个进程从提出请求到运行完成的时间

  • 响应时间RT (Response Time)

    从提出请求到第一次回应的时间

  • 其他

    • CPU 利用率 (CPU Utilization)

      CPU做有效工作的时间比例

    • 等待时间 (Waitingtime)

      每个进程在就绪队列 (ready queue) 中等待的时间


二.设计调度算法时需要考虑的问题

设计调度算法时要考虑以下几个问题:

  • 进程控制块PCB中

    需要记录哪些与CPU调度有关的信息

  • 进程优先级及就绪队列的组织

  • 抢占式调度与非抢占式调度
  • I/O密集型与CPU密集型进程
  • 时间片

1.进程优先级(数)

优先级和优先数是两个不同的概念。

优先级是表现进程的重要性和紧迫性。 优先数是一个数值,它反映了某一个优先级

有些系统像 UNIX 优先数小的优先级高,但是不能完全根据数的大小来决定优先级的高低。

根据优先级是否能改变分为静态优先级和动态优先级。

静态优先指在进程创建时,指定优先级之后在进程运行的过程中,这个优先级不再发生改变。

动态优先级是在进程运行过程中,优先级的级别还会不断地调整。

有的时候需要动态优先级,比如当一个进程在就绪队列当中等待的时间很长的时候,要提升它的优先级,让它尽快有机会得到CPU去运行。

2.进程就绪队列组织

按照优先级来排队 :

可以按照优先级来组织就绪队列。当创建一个新的进程的时候,根据它的优先级排不同的就绪队列,在这里设定n个就绪队列优先级,不同的优先级进入不同的就绪队列。 就绪队列 1 的优先级是最高的,当调度程序选择进程的时候,首先应该从高优先级的队列来选择进程 。如果高优先级队列没有进程了,再从次高就绪队列来选择进程。

另一种排队方式:

所有的进程第一次创建之后都进到第一级就绪队列,随着进程的运行可能会降低某些进程的优先级。比如当一个进程分配给它的时间片用完了,那么它就会降一级,降到第二级就绪队列。 如果它经常地用完时间片,慢慢的这个进程就会降低到最后一级就绪队列。进程调度首先在第一级队列里选,说明第一级就绪队列的优先级比较高。如果这个队列是空的,那么调度就会从其他的就绪队列里头选择进程。如果进程已经进到了最后一级队列,那么它的优先级就越来越低,它被调度上 CPU 的机会就会变得很小。

3.占用CPU的方式—抢占与非抢占

指占用CPU的方式:

  • 可抢占式Preemptive(可剥夺式)

当有比正在运行的进程优先级更高的进程就绪时,系统可强行剥夺正在运行进程的CPU,提供给具有更高优先级的进程使用。

  • 不可抢占式Non-preemptive(不可剥夺式)

某一进程被调度运行后,除非由于它自身的原因不能运行,否则一直运行下去

4.I/O密集型与CPU密集型进程

按进程执行过程中的行为划分:

  • I/O密集型或I/O型(I/O-bound)

    频繁的进行I/O,通常会花费很多时间等待I/O操作的完成

  • CPU密集型或CPU型或计算密集型(CPU-bound)

    需要大量的CPU时间进行计算

在设计调度算法时,通常会对I/O型的进程会有一些友好,希望更多的I/O型进程早一点上CPU运行。

因为这些进程上CPU 之后只用了很短的一下,CPU时间就让出CPU,因为它要去做其它的输入输出操作。因此对于一般的调度程序,都会对I/O型进程更偏好一些。

5.时间片

时间片指的是一个时间段,指分配给调度上CPU的进程,允许这个进程在CPU上执行多长时间,它是一个时间的长度。

那么如何选择时间片呢? 应该考虑很多的因素:

  • 进程切换的开销有多大

  • 进程对响应时间的要求

  • 系统当中有多少进程处于就绪

  • CPU的能力有多大

  • 进程的行为(不同进程可能区别对待)

    因此在设计时间片大小的时候要考虑到这些因素。 具体分配时间片的方式会在时间片轮转算法时进行介绍。


三.批处理系统中采用的调度算法

介绍批处理系统中的常用的调度算法:

  • 先来先服务 (FCFS-First Come First Serve)
  • 最短作业优先 (SJF-Shortest Job First)
  • 最短剩余时间优先 (SRTN-Shortest Remaining Time Next)
  • 最高相应比优先 (HRRN-Highest Response Ratio Next)

在批处理操作系统中对于算法的要求往往是看它的带来的 吞吐量大小,周转时间,CPU 利用率公平和平衡 这几个因素。

1.先来先服务FCFS

(1).概念

先来先服务调度算法也称为先进先出。指的是按照进程就绪的先后顺序来使用 CPU。先进先出调用算法是一个非抢占式的调度算法。

优点:

  • 公平 (谁先就绪谁先上CPU)
  • 实现简单 (维护一个队列就可以了)

选择进程时从队首选择, 新就绪的进程排在队尾。

缺点:

  • 长进程后面的短进程需要等很长时间,不利于用户体验

如果有一个短的进程排在了一个长时间运行进程的后面, 它需要等待的时间比较长, 这样使得用户体验不够友好。

(2).举例

假设有三个进程,按照P1、P2、P3就绪。 P1进程需要运行24秒,P2和P3分别需要3秒计算。

采用先来先服务的调度算法调度:

同样还是这个例子, 改变调度的顺序:

可以看到平均周转时间降低到了13秒。

所以可以看到改变调度的顺序,也就是调度算法的改变会改善平均周转时间, 进而可能改善了响应时间这些指标。

2.短作业优先SJF

(1).概念

短作业优先指的是具有最短完成时间的进程优先执行

  • 非抢占式

如果短作业优先调度算法再改进一下: 加抢占模式,变成了抢占式的版本。这就是最短剩余时间优先调度算法

  • 抢占式

所谓最短剩余时间就是当 一个新就绪的进程正在当前运行的进程它的 剩余的运行时间短的时候, 系统就会去抢占当前的进程,然后把CPU交给这个运行时间更短的进程

因为在一个短作业运行的过程中,可能有一个新的进程创建出来,或者一个进程从等待变成就绪,那么它剩余的时间比当前正在运行的这个进程剩余的这个运行时间还短, 就要抢占了。

(2).举例

有四个进程到达时刻不是同时到达的,有不同的时刻:

(3).优缺点

优点:

  • 在所有进程同时可运行时,采用SJF调度算法可以得到最短的平均周转时间。

缺点:

  • 源源不断的短任务到来,可能使长的任务长时间得不到运行 → 产生 “饥饿”现象 (starvation)

3.最高相应比优先 HRRN

既有先来先服务的优点,又有短作业优点,,这是操作系统当中的一个常用的手段——折衷权衡。 这种调度算法其中之一就是最高响应比优先

基本思想是这样的:

调度时,首先计算每个进程的响应比R;之后,总是选择R最高的进程执行。

其中一种方案:

很明显地看到,如果处理时间短,也就是短作业,那么分母小,整个的值就大,因此响应比就大。

如果很早就绪了,在就绪队列中等的时间非常长,那等待时间就变得越来越大, 最后响应比变得非常大,被调度上 CPU。


四.交互式系统的调度算法

介绍交互式系统中所采用的一些调度算法:

  • 轮转调度 (RR-Round Robin)
  • 最高优先级调度 (HPF—Highest Priority First)
  • 多级反馈队列 (Multiple feedback queue)
  • 最短进程优先 (Shortest Process Next)

追求的指标主要是响应时间,公平,资源的平衡使用。最短进程优先调度算法呢短作业优先调度算法差不多,就不再介绍。

1.时间片轮转算法

(1).概念

左图看到当前正在运行的是B进程,排在它后面的是F进程。当B进程用完它的时间片之后就回到队列的末位,调度就会选择下一个进程,所以右图当前运行进程F上CPU。这就是一个时间片轮转,然后F运行完它的时间片后就继续去排队。队列里面的每一个进程都有机会轮流上CPU。

目标:

  • 改善短作业(短任务)的平均响应时间。

具体做法:

  • 周期性地切换

  • 每个进程分配一个时间片

  • 通过了时钟中断引发轮换

以此来达到改善短作业的平均响应时间的目标。

(2).如何选择合适的时间片

如果选择的时间片太长:

上图可以看到这个进程开始运行后,给它一个时间片,在没有用完时间片的前提下就已经完成了一个响应。如果系统中绝大部分进程都不到一个时间片就可以完成响应的话,那么时间片轮转算法实际上已经退化成了一个先来先服务的这种算法。另外如果时间片过长会延长某些进程的响应时间。

如果选择的时间片过短:

如果时间片太短,响应时间也会变长,频繁地去切换,那切换这个行为本身会带来开销。前面已经讲过上下文切换是有开销的,所以切换也就浪费了CPU的时间。

(3).优缺点

优点

  • 公平 (进程轮流上CPU)

  • 有利于交互式计算,响应时间快

  • 对于不同大小的进程是有利的

缺点

  • 由于进程切换,时间片轮转算法要花费较高的开销 (得让切换所带来的开销对于时间片来说能做到忽略不计)

  • 对于大小相同的进程是不利的

(4).虚拟轮转法 VIRTUAL RR

时间片轮转算法往往不区分I/O型进程与CPU型进程。这样会给I/O型进程带来一定的不公平。

因为当一个CPU型进程被调度上CPU之后,用完它的时间片就会去重新排队,下一次再调度上CPU又用会完一个完整时间片。而I/O型进程被调度上CPU之后,运行完它的时间片,可能运行的很短就完成了它的任务,然后就去等待I/O,进入等待队列。一旦等待的结果到来,又变成一个就绪再次上 CPU,它又没有用完分配给它的时间片就结束了任务。所以CPU型的进程总是用完给它的时间片。 所以它占用了更多的 CPU 时间而I/O型进程总是用不完它的时间片,所以这个调度算法对它有些不公平。

上图是设计的虚拟轮转法:

当一个I/O型进程让出 CPU进到等待队列,从等待队列又重新回到就绪状态的时候。不去进入原来的就绪队列,会单独为它设置一个队列,叫做辅助队列。也就是所有I/O型的进程从等待变成就绪的时会进到这个队列。调度算法在选择进程的时候首先从这个辅助队列里去选择I/O 型进程。I/O 型进程上CPU之后,又很快地放弃了CPU进入等待直到辅助队列为空。实践表明这个方案改善了这个对I/O型进程的一种不公平性。

2.最高优先级调度算法

(1).概念

最高优先级调度算法思想比较简单,总是选择优先级最高去执行。

通常情况下:

  • 系统进程优先级 高于 用户进程
  • 前台进程优先级 高于 后台进程
  • 操作系统更偏好 I/O型进程

优先级可以是静态不变的,也可以动态调整。优先数可以决定优先级。就绪队列可以按照优先级组织

特点:

  • 实现简单
  • 不公平 (出现饥饿现象)

(2).优先级反转问题

如果是基于优先级的抢占式调度算法,就会出现一个优先级反转问题。

优先级反转又称:优先级反置、翻转、倒挂

现象:

一个低优先级进程持有一个高优先级进程所需要的资源,使得高优先级进程等待低优先级进程运行。

例子:

影响:

  • 系统错误
  • 高优先级进程停滞不前,导致系统性能降低

解决方案

  • 设置优先级上限

    凡是进入临界区的进程优先级都是最高的。 不在临界区的进程优先级都会比这个进入临界区的这进程优先级要低。这样的话就可以执行完成,然后把临界区还回去。

  • 优先级继承

    如果一个低优先级的进程阻碍了一个高优先级进程执行,它可以临时地继承这个高优先级的这个进程的优先级,一下子把自己优先级继承到这个高优先级的这个程度。那么就可以去运行,然后把临界区还回去。

  • 使用中断禁止

    凡是进入临界区的进程,那么就不再响应中断的。 直到出临界区才响应中断,这样就保护了这个进程,让它继续去执行。

3.多级反馈队列调度算法

多级反馈队列调度算法是UNIX 的一个分支,是BSD5.3版所采用的调度算法。它是在前面各种调度算法的基础之上提出的一个综合的调度算法,是在考虑了各种因素之后进行折中权衡的一个结果。

多级反馈队列调度算法的基本思想:

  1. 设置多个就绪队列,第一级队列优先级最高

  2. 给不同就绪队列中的进程分配长度不同的时间片,第一级队列优先级最高但时间片最小;随着队列优先级别的降低,时间片增大

  3. 在进行调度时,先从优先级高的进行。当第一级队列为空时,在第二级队列调度,以此类推

  4. 各级队列按照时间片轮转方式进行调度

  5. 当一个新创建进程就绪后,进入第一级队列

  6. 进程用完时间片而放弃CPU,进入下一级就绪队列

  7. 由于阻塞而放弃CPU的进程进入相应的等待队列,一旦等待的事件发生,该进程回到原来一级就绪队列

    可以根据不同的情况来设计不同的方案以体现系统对这一类进程的偏好程度。

    比如说进程是回到原来一级就绪队列的队首还是队尾?如果回到队首,说明系统对这类进程更加友好

    另外当进程再度被调度上 CPU 之后是让它运行完剩余的时间片还是重新给它分配一个完整的时间片让它去运行? 也体现了系统对这类进程的偏好程度。

以上为非抢占式的。

若允许抢占:

当有一个更高优先级的进程就绪的时候可以抢占正在运行进程的CPU,那么被抢占的进程会回到原来一级就绪队列的末尾。

当然也可以有不同的设计方案比如说回到原来一级就绪队列的队首。

当这个进程再度被调度上CPU时可以运行完它刚才剩余的时间片,也可以重新给它一个完整的新的时间片让它运行。因此又派生出不同的设计方案 。

上图反映了一个进程在队列里头的一些迁移活动。

当创建一个新的进程时,所有的进程都进入第一级队列。

如果是 I/O 型的进程,那么它可能被调度上 CPU 之后很短时间就去等待I/O,当它从等待队列又回到就绪队列的时候,让它回到原来一级就绪队列,所以优先级没有降低,被调度上 CPU 的机会很多。

但是对于CPU 型的进程,它被调度上CPU用完了一个时间片之后就会回到下一级队列。如果每次都用完了它的时间片,它就会降级。可能一个CPU 型的进程就慢慢降到了优先级最低的这个队列里。

因此可以看到这个调度算法可以慢慢地区分出来哪些进程是CPU型进程,哪些进程是I/O型进程,很显然多级反馈队列调度算法对I/O型进程更偏好一点,对CPU型进程呢不太有利。但是它也做了一些弥补,比如说优先级高的队列时间片短,而优先级低的队列时间片会很大,所以当低优先级的CPU型进程被调度上CPU之后,它可以运行更长的时间。这里也是一种平衡的结果。

4.各种调度算法的比较

5.多处理器调度算法需要考虑到的问题

  • 不仅要决定选择哪一个进程执行

    还需要决定在哪一个CPU上执行

  • 要考虑进程在多个CPU之间迁移时的开销

    • 高速缓存失效、TLB失效

    • 尽可能使进程总是在同一个CPU上执行

      如果每个进程可以调度到所有CPU上,假如进程上次在CPU1上执行,本次被调度到CPU2,则会增加高速缓存失效、TLB失效;如果每个进程尽量调度到指定的CPU上,各种失效就会减少

  • 考虑负载均衡问题


五.典型操作系统的调度算法

  • UNIX —— 动态优先数法
  • 5.3BSD —— 多级反馈队列法
  • Linux —— 抢占式调度
  • Windows —— 基于优先级的抢占式多任务调度
  • Solaris —— 综合调度算法

1.Linux调度算法的发展过程

2.Windows线程调度

(1).基本概念

由于Windows操作系统支持内核级线程,所以CPU的调度单位是线程

Windows的线程调度采用的是基于动态优先级的,抢占式调度,同时结合了时间配额的调整

基本思想:

  • 就绪线程按优先级进入相应队列
  • 系统总是选择优先级最高的就绪线程运行
  • 同一优先级的各线程按时间片轮转进行调度
  • 多CPU系统中允许多个线程并行运行

引发线程调度的条件:

  • 线程正常终止或由于某种错误而终止
  • 新线程创建或一个等待线程变成就绪
  • 当一个线程从运行态进入阻塞态
  • 当一个线程从运行态变为就绪态

然后再此基础上又添加了两个条件:

  • 一个线程的优先级改变了
  • 一个线程改变了它的亲和(Affinity)处理机集合

线程的亲和处理机集合:有这样一个处理机的集合,允许线程在这个处理机集合上执行,除了处理机集合之外的其他处理机空闲,这个线程也不能执行。这个集合就是这个线程的亲和处理机集合。

如果这个集合改变了,比如增加了一个新的处理机在这个集合当中,那么就可以引发新的线程调度。

(2).线程优先级

Windows把线程分成了32 个优先级分成了三类:

实时优先级的线程:一旦确定了优先级,就不会再改变了。

可变优先级的线程:它的优先级可以在一定的范围内提升或者是降低。

对于可变优先级的线程,可以区分为 基本优先级当前优先级

通常系统会安排一个零页线程,即给物理内存清零的线程,把它的级别安排在零集,那么当没有其他进程运行的时候,有一个线程可以做这样的工作。

(3).线程的时间配额

时间配额不是一个时间长度值而是一个称为配额单位(quantum unit)的一个整数。一个线程用完了自己的时间配额时,如果没有其他相 同优先级的线程,Windows将重新给该线程分配一个新的时间配额,让它继续运行。

时间配额的特殊作用:

  • 假设用户首先启动了一个运行时间很长的电子表格计算程序,然后切换到一个游戏程序(需要复杂图形计算并显示,CPU型)

  • 如果前台的游戏进程提高它的优先级,则后台的电子表格计算进程就几乎得不到CPU时间了

  • 所以增加游戏进程的时间配额,则不会停止执行电子表格计算, 也能给游戏进程的CPU时间多一些。

(4).调度策略

主动切换

有一个正在运行的线程,优先级是20。在运行过程中,由于需要等待输入输出的结果,那么这个线程就转到了阻塞态让出了 CPU。 调度程序会去选择一个新的线程上CPU运行。

抢占

如果刚才被阻塞的线程被唤醒了,由于它的优先级高,它会去抢占CPU去运行,那么被抢占的这个线程就回到了就绪队列。

当线程被抢占时,它被放回相应优先级的就绪队列的队首

  • 处于实时优先级的线程在被抢占时,时间配额被重置为一个完整的时间配额

  • 处于可变优先级的线程在被抢占时,时间配额不变,重新得到CPU后将运行剩余的时间配额

时间配额用完

假设线程A的时间配额用完

  • A的优先级没有降低
    • 如果队列中有其他就绪线程,选择下一个线程执行,A回到原来就绪队列末尾
    • 如果队列中没有其他就绪线程,系统给线程A分配一个新的时间配额,让它继续运行
  • A的优先级降低了
    • Windows 将选择一个更高优先级的线程

为什么一个线程用完了它的时间配额后,优先级会被降低?

那是因为这个线程在此之前,优先级被提升过。

线程优先级提升和与时间配额挑整

Windows的调度策略

  • 如何体现对某类线程具有倾向性?
  • 如何解决由于调度策略中潜在的不公平性而带来饥饿现象?
  • 如何改善系统吞吐量、响应时间等整体特征?

解决方案

  • 提升线程的优先级
  • 给线程分配一个很大的时间配额

线程优先级提升

下列5种情况,Windows会提升线程的当前优先级:

  • I/O操作完成
  • 信号量或事件等待结束
  • 前台进程中的线程完成一个等待操作
  • 由于窗口活动而唤醒窗口线程
  • 线程处于就绪态超过了一定的时间还没有运行 —— “饥饿”现象

线程优先级的提升是针对可变优先级范围内(1至15)的线程优先级。

例子:

  1. I/O操作完成后的线程优先级提升:
  • 在完成I/O操作后,Windows将临时提升等待该操作 线程的优先级,保证该线程能更快上CPU运行进行数据处理
  • 优先级的提升值由设备驱动程序决定,提升建议值保存在系统文件Wdm.hNtddk.h
  • 优先级的提升幅度与对I/O请求的响应时间要求是一 致的,响应时间要求越高,优先级提升幅度越大
  • 设备驱动程序在完成I/O请求时通过内核函数IoCompleteRequest来指定优先级提升的幅度
  • 为避免不公平,在I/O操作完成唤醒等待线程时会将该线程的时间配额减1
  1. “饥饿”线程的优先级提升
  • 系统线程平衡集管理器(balance set manager)每秒钟扫描一次就绪队列,发现是否存在等待时间超过300个时钟中断间隔的线程

  • 如果存在,平衡集管理器将这些线程的优先级提升到15 (最高),并分配给它一个长度为正常值4倍的时间配额

  • 因此当被提升的线程用完它的时间配额后,立即衰 减到它原来的基本优先级

0%