处理机调度

🔥 高优先级
选择题必考内容,重点掌握 调度指标的计算各种调度算法的实现细节,调度的实现 和 进程上下文切换相比之下考察比较少。

调度指标

在操作系统里,调度(Scheduling) 是把 CPU 时间合理分配给多个进程(或线程)的核心机制。调度的好坏直接决定系统的响应速度、吞吐能力以及资源利用效率。为了衡量调度策略的优劣,我们通常用一组 调度指标 来量化:

  1. 系统层面的宏观指标——关注整个计算机系统的运行状态,如 CPU 的利用率、系统整体的吞吐量等。这类指标帮助我们了解系统在整体负载下是否“忙碌”或出现瓶颈。
  2. 进程层面的微观指标——关注单个进程在调度器眼中的表现,包括它何时进入调度队列、等待多久才被分配 CPU、实际执行多长时间以及最终何时完成等。这类指标可以帮助我们比较不同调度算法(FCFS、SJF、RR、优先级调度等)对单个作业的影响。

系统层面

系统层面主要关注 CPU 利用率和吞吐量这两个指标:

系统指标含义
CPU 利用率CPU 活跃时间与总观察时间的比率。通常表示为百分比
系统吞吐量操作系统单位时间内系统完成的工作量或进程数

进程层面

从进程视角而言,进程从被创建到执行结束会有一系列时间周期作为指标:

到达时间,AT
完成时间,CT
等待时间,WT
时间线
要求服务时间,BT
周转时间,TAT
进程调度指标英文含义
到达时间AT, Arrival Time进程在何时到达调度器,即何时被提交
等待时间WT, Waiting Time进程等待了多长时间才开始执行
要求服务时间BT, Burst Time进程从开始执行到结束需要多少时间
完成时间CT, Completion Time进程何时执行完成
周转时间TAT, Turnaround Time进程从提交到完成的时间,TAT = CT - AT = WT + BT

系统调度过程

为了有效地管理和调度进程,操作系统通常采用多级调度机制。这些调度机制分为三个层次:高级调度中级调度初级调度

Pull of
job in
disk
Pull of...
Ready Queue
Ready Queue
Waiting Queue
Waiting Queue
I/O
I/O
Dispatcher
Dispatcher
CPU
CPU
END
END
Long term
Scheduler
Long term...
Short term
Scheduler
Short term...
Mid-term
Scheduler
Mid-term...
Mid-term
Scheduler
Mid-term...
Text is not SVG - cannot display
  1. 高级调度(长程调度,Long-term Scheduling):
    • 功能:高级调度 主要决定哪些进程应当被加载到内存中成为一个可运行的进程。
    • 主要目标:保持内存中适当数量的进程。不要过多也不要过少。
    • 当进程首次进入系统时,它们首先被放置在磁盘的一个区域,称为作业池。高级调度器从作业池中选择进程,根据某种策略将其加载到内存中,从而使其成为一个可运行的进程。
  2. 中级调度(中程调度,Mid-term Scheduling):
    • 功能:中级调度 涉及到进程的暂停和重启。当系统的进程数超过内存容量时,中级调度器可能会将一些进程从内存移出到磁盘上(这称为交换或页面置换),从而为新的或等待的进程腾出空间。
    • 主要目标:为高级调度初级调度器优化内存使用。
    • 中级调度器在必要时将进程从内存交换到磁盘,并在适当的时机将其交换回内存。
  3. 初级调度(短程调度,Short-term Scheduling):
    • 功能:初级调度 决定哪个进程应当被赋予 CPU 时间片,即决定下一个运行在处理器上的进程。
    • 主要目标:确保 CPU 的高效利用。
    • 它的决策频率非常高,因为在多任务环境中,每个时间片的长度可能只有几十毫秒。因此,初级调度器必须是非常快速的。

调度的实现

调度器

调度器/调度程序(scheduler):

  • 调度器 是操作系统中负责决定下一个要执行的进程或线程的部分。
  • 基于特定的调度算法(如轮转、优先级调度、短作业优先等),它决定哪个进程或线程应当获得 CPU 时间。
  • 调度器 通常分为长程、中程和短程调度器,如前文所述。

调度时机

可能引发调度的事件大致有以下几类:

  1. 当前进程主动让出 CPU:进程正常结束、异常终止,或因等待 I/O、等待信号量等原因由运行态转为阻塞态。
  2. 有进程进入就绪队列:新进程被创建,或某个阻塞进程等待的事件已完成(如 I/O 完成)而转为就绪态。
  3. 时间片用完:时钟中断到达,当前进程用完了分配给它的时间片。

其中第 1 类事件的共同点是 当前进程已经无法继续占用 CPU,因此无论采用哪种调度方式都必然发生调度;而第 2、3 类事件的共同点是 当前进程本来还可以继续运行,是否此刻切换进程,取决于系统采用的是抢占式还是非抢占式调度。

调度方式

非抢占式调度(Non-Preemptive,又称非剥夺方式):一旦把 CPU 分配给某个进程,就让它一直运行下去,直到它 自己结束或主动转为阻塞态,才把 CPU 交给下一个进程。也就是说,只有上面第 1 类事件才会触发调度:

  • 新进程创建、更高优先级的进程变为就绪 —— 不调度,新到达的进程只能在就绪队列中排队等待。
  • 时间片到期 —— 不适用(非抢占式算法本身不使用时间片)。

抢占式调度(Preemptive,又称剥夺方式):当进程正在运行时,操作系统可以强行中断它、把它放回就绪队列,再把 CPU 分配给另一个进程。除第 1 类事件外,第 2、3 类事件同样可能触发调度:

  • 新进程创建,且其优先级(或剩余运行时间等指标)优于当前进程 —— 立即抢占,当前进程由运行态回到就绪态。
  • 阻塞进程被唤醒进入就绪队列,且优于当前进程 —— 立即抢占
  • 时间片用完 —— 必然切换(如时间片轮转)。

因此,判断某个算法是否抢占式,一个直观的检验标准是:

一个新进程到达时,正在运行的进程会不会被打断? 会,就是抢占式;不会,就是非抢占式。

事件非抢占式抢占式
当前进程结束 / 主动阻塞调度调度
新进程到达就绪队列不调度,排队等待若优于当前进程则立即抢占
阻塞进程被唤醒进入就绪队列不调度,排队等待若优于当前进程则立即抢占
时间片用完不使用时间片强制切换,当前进程排到队尾

下图以“P1 先到达、P2 后到达且优先级更高”为例,对比两种调度方式在 P2 到达这一时刻的不同处理:

t = 3:P2 到达(优先级更高)非抢占式Non-PreemptiveP1 一直运行到结束P2不调度:新进程只能排队P2 在就绪队列等待 5抢占式PreemptiveP1P2P1(恢复执行)立即调度:P1 被剥夺 CPU,运行态 → 就绪态P1 在就绪队列等待 40123456789101112tP1:AT = 0,BT = 8,低优先级P2:AT = 3,BT = 4,高优先级就绪等待

闲逛进程

闲逛进程(Idle Process)是操作系统中的一个特殊进程,当系统没有任何其他可运行的进程时,调度器会将 CPU 的控制权交给这个进程。闲逛进程的主要目的是确保在没有任务可执行的情况下,CPU 不会空转,从而防止 CPU 进入不受控制的状态。

在 Linux 操作系统中,闲逛进程的进程 ID 通常是 0,被称为 swapper 或 idle task。它是系统启动时创建的第一个进程,始终在内核态运行,确保当没有其他可调度任务时,CPU 有事情可做。

在 Windows 系统中,闲逛进程被称为 System Idle Process,同样用于在系统空闲时占据 CPU 时间,以维持系统的运行稳定。如下图所示:

system idle process

两种线程的调度

  • 内核级线程:由操作系统内核直接支持的线程。操作系统知道这些线程的存在,并可以直接进行调度。
  • 用户级线程:完全在用户空间中实现的线程,不需要内核的介入。
  • 对于 内核级线程,操作系统可以直接调度它们,并可以利用多核或多处理器的优势。
  • 对于 用户级线程,因为内核不知道它们的存在,所以内核无法直接调度它们。线程之间的上下文切换可能比 内核级线程 更快,但在多处理器系统中,它们可能无法充分利用所有的处理器。

调度算法

根据 是否可抢占 可以对调度算法进行如下分类:

  • 非抢占型调度算法:先来先服务、最短任务优先、最高响应比优先
  • 抢占型调度算法:时间片轮转、多级反馈队列
调度算法
抢占式
非抢占式
时间片轮转
多级反馈队列
优先级调度
先来先服务
最短作业优先
最高响应比优先

先来先服务

先来先服务(First-Come, First-Served,FCFS)按照进程到达的顺序 分配依次执行。先到达的进程先执行,后续进程等待直到前一个进程执行才能进一步执行。

0
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
21
22
23
24
到达时间
要求服务时间
0 ms
5 ms
P2
1 ms
3 ms
P3
2 ms
7 ms
3 ms
6 ms
P1
P4
Process ID
P1
P2
P3
P4

最短作业优先

最短作业优先(Shortest Job First,SJF)算法在从就绪队列中选择进程时,会 选择运行时间最短 的进程进行执行。

在题目中进程的运行时间一般都是给定的,所以 SJF 算法比较容易实现。但是在真实的系统中进程的运行时间是不确定的,所以在使用该算法时操作系统需要对进程的运行时间进行预估。

1
1
2
1
2
3
1
2
3
4
1
2
3
4
5
Jobs = [4, 3, 7, 1, 2]
waiting time
= 0 + 1 = 1
waiting time
= 1 + 2 = 3
waiting time
= 3 + 3 = 6
waiting time
= 6 + 4 = 10
waiting time
= 10 + 7 = 17
Jobs = [4, 3, 7, 1, 2]
Jobs = [4, 3, 7, 1, 2]
Jobs = [4, 3, 7, 1, 2]
Jobs = [4, 3, 71, 2]

最高响应比优先

最高响应比优先(Highest Response Ratio Next,HRRN)算法从就绪队列中选择 响应比 最高的进程进行执行。

其中 响应比(Response Ratio)的计算公式如下:

其中 (Waiting Time)为进程的等待时间, (Burst Time)为进程的要求服务时间(从执行开始到结束所需时间)。

这种计算策略可以有效地避免饥饿现象,即一个进程等待了很长时间但仍没有得到执行。一个进程的等待时间越长,其 响应比 就会更大,进而优先得到执行机会。一个进程的执行时间很长,其 响应比 就会越小,会优先调度其他进程。


0
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
21
22
23
24
到达时间
要求服务时间
0 ms
5 ms
P2
1 ms
3 ms
P3
2 ms
8 ms
3 ms
6 ms
P1
P4
Process ID
P1
P2
P3
P4
  • 时刻 0:只有 P1 到达,执行 P1。
  • 时刻 5:P1 执行完成。P2 的 响应比 为 (4 + 3) / 3 ≈ 2.33,P3 的 响应比 为 (3 + 8) / 8 = 1.375,P4 的 响应比 为 (2 + 6) / 6 ≈ 1.33,此时 P2 的 响应比 最大,执行 P2。
  • 时刻 8:P2 执行完成。P3 的 响应比 为 (6 + 8) / 8 = 1.75,P4 的 响应比 为 (5 + 6) / 6 ≈ 1.83。此时 P4 的 响应比 更大,执行 P4。
  • 时刻 14:P4 执行完成,只剩下 P3 了,最后执行 P3。

所以进程的执行顺序为 P1、P2、P4、P3,每个进程的时间指标如下表所示:

进程号到达时间要求服务时间完成时间周转时间等待时间
P105550
P213874
P43614115
P328232112

优先级调度

优先级调度是一种基于进程优先级的调度算法,广泛应用于操作系统中。根据是否允许中断当前正在执行的进程,优先级调度可分为 非抢占式优先级调度抢占式优先级调度 两种形式。

非抢占式优先级调度

非抢占式优先级调度 中,调度器总是从就绪队列(等待队列)中选择优先级最高的进程执行。一旦某个进程开始执行,它将持续运行直到完成(或主动释放 CPU,例如进入等待 I/O 状态)。在此期间,即使有更高优先级的进程到达并加入就绪队列,当前进程也不会被中断,而是继续执行直到结束。

注意

在常见的操作系统和调度算法中,优先级的值越小,优先级越高

比如对于 Unix 系统,使用 nice 值来表示优先级:

  • nice 值越低,进程获得 CPU 时间的机会越多。
抢占式优先级调度

抢占式优先级调度 旨在确保系统中任何时刻运行的进程始终是优先级最高的。当一个更高优先级的进程到达时,调度器会立即暂停当前运行的低优先级进程(将其挂起并加入就绪队列),然后将 CPU 分配给新到达的高优先级进程。

下图给出了两种优先级调度方式的实例对比,其中绿色的进程表示执行态,黄色表示就绪态:

到达时间
要求服务时间
0 ms
4 ms
P2
1 ms
3 ms
P3
2 ms
6 ms
P1
Process ID
优先级
2
1
3
0
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
21
22
23
24
P1
P2
P3
0
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
21
22
23
24
P1
P2
P3
抢占式
Preemptive
非抢占式
Non-Preemptive

时间片轮转

RR 调度

时间片轮转(Round Robin,RR) 是一种专门用于 分时系统 的调度算法。系统为每个进程分配一个固定大小的 时间片(time quantum),就绪进程按照 FIFO 顺序组织成就绪队列,CPU 按队列顺序轮流为进程分配时间片。

调度过程可以概括为:

  1. 就绪队列队首 取出一个进程运行。
  2. 若进程在一个时间片内 执行完毕,则进程退出,调度器从队列中选择下一个进程。
  3. 若时间片用完而进程 尚未执行完毕,则发生一次 时间片中断,该进程重新进入 就绪队列队尾,CPU 转而执行队首的下一个进程。
  4. 如果运行过程中有新的进程到达,则新进程进入 就绪队列队尾
  5. 重复上述过程,直到所有进程执行完毕。
时间片轮转调度:就绪队列结构与调度流程顶部展示就绪队列的 FIFO 结构,包含多个等待进程;下方展示调度流程:取出队首进程运行一个时间片,判断是否执行完毕,完毕则退出,未完毕则重新进入队尾。新进程到达就绪队列(FIFO)P1P2P3P4取出运行取出队首进程运行占用一个时间片时间片内完成?时间片到期重新进入队尾返回队列进程执行完毕退出系统,调度下一进程

因此,RR 的核心并不是简单地“按照进程编号轮流执行”,而是:

维护一个就绪队列,每次只允许队首进程最多运行一个时间片;未完成的进程重新排到队尾。

轮转的语义

例如,若时间片为 ,某时刻就绪队列为:

则调度过程可能为:

这里的“轮转”体现为:进程运行一个时间片后,如果没有结束,就从队首移动到队尾。

需要特别注意,RR 并不意味着每个进程最终获得完全相同的 CPU 时间。它保证的是在持续存在于就绪队列中的进程之间,CPU 使用机会大致公平;如果某个进程提前结束,或者某些进程在等待 I/O 而阻塞,就不会继续占用时间片。

举个实际例子,假设时间片大小为 3,不同进程在不同时刻加入就绪队列,那么调度过程如下图所示:

0
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
Timeline
P1 (0, 1)
P2 (0, 2)
P3 (0, 4)
P4 (0, 6)
P5 (0, 6)
P6 (5, 8)
P7 (5, 8)
P8 (5, 4)
P9 (5, 2)
P10 (5, 1)
Process (Arrival Time, Burst Time)

调度器按照轮询的方式依次遍历进程,每个进程只有执行时间片内的时间,之后便进入等待状态:

进程 (Process)到达时间 (Arrival Time)要求服务时间 (Burst Time)完成时间 (Completion Time)周转时间 (Turnaround Time)
P10111
P20233
P3042525
P4062828
P5063131
P6584035
P7584237
P8543833
P9522318
P10512419

时间片的影响

时间片 的大小会显著影响 RR 的性能:

  • 时间片过大:RR 会逐渐接近 FCFS。进程往往一次运行很长时间,交互响应性变差。
  • 时间片过小:进程切换非常频繁,虽然响应时间较好,但会产生大量 上下文切换开销,降低 CPU 的有效利用率。
  • 因此,实际系统需要选择一个合适的时间片,使 响应速度上下文切换开销 之间取得平衡。

可以将其理解为:

越小,进程之间的切换越频繁。

多级反馈队列

多级反馈队列(Multilevel Feedback Queue)这是一种混合算法,将进程分为 多个队列,每个队列有不同的优先级和时间片大小。

高优先级队列优先调度,时间片较短,适合交互型进程;低优先级队列时间片较长,适合计算密集型任务。新进程通常进入最高优先级队列,若在时间片内未完成,则移到下一级队列;若因 I/O 等待阻塞,完成后可能返回较高优先级队列。

CPU
CPU
CPU
Level 1 Queue
(Round Robin, Quantum = 8)
Level 2 Queue
(Round Robin, Quantum = 16)
Level n Queue
(FCFS)
Finish
Finish
Finish
Not Finish
Not Finish

多级反馈队列根据进程行为调整其优先级。例如,占用 CPU 过多的进程会被降级,而频繁等待 I/O 的进程可能被提升。这种设计兼顾了快速响应、公平性和资源利用率。

上下文切换

进程的上下文是进程执行的环境。在操作系统中,它指的是一个进程在特定时间点上的系统状态,包括多种信息,这些信息使得进程在被中断后可以再次恢复并继续执行。当操作系统从一个进程切换到另一个进程时,它会保存当前进程的上下文并恢复下一个进程的上下文。这个过程被称为 上下文切换

等待
在 PCB0 中保存 P0 的状态
从 PCB1 中恢复 P1 的状态
在 PCB0 中保存 P1 的状态
从 PCB1 中恢复 P0 的状态
系统中断或调用
Process 0
Process 1
执行
执行
执行
等待
等待

进程上下文内容

  1. 寄存器值:这包括通用寄存器、程序计数器、栈指针、状态寄存器等。它们保存了进程的当前执行位置和状态。
  2. 程序计数器:表示进程的下一个指令的位置。
  3. 虚拟内存信息:这包括进程的页表、页目录等信息,描述了进程的地址空间布局。
  4. I/O 状态信息:包括打开的文件描述符、网络连接、I/O 指针等。
  5. CPU 调度信息:例如进程优先级、计划器状态等。
  6. 资源使用情况:这可能包括该进程所使用的各种资源的跟踪信息,如内存、文件句柄等。

上下文切换流程

  1. 保存当前进程的状态:操作系统保存当前正在运行的进程的上下文。这意味着它会将当前的寄存器值、程序计数器等保存到进程的进程控制块(PCB)中。
  2. 选择下一个要执行的进程:调度器决定下一个要运行的进程。
  3. 恢复下一个进程的状态:操作系统从新进程的 PCB 中恢复其上下文信息,包括寄存器值、程序计数器等。
  4. 开始执行新进程