早期的单任务操作系统,一次只能处理一个任务,且只有当前任务执行完成后,其它任务才能执行。这样的进程执行方式,CPU 资源经常处于空闲状态。例如当前执行的进程正在进行 I/O 操作,此时 CPU 就处于空闲状态,因为当前进程尚未执行完毕,其它进程也无法使用 CPU,所以 CPU 只能等待 I/O 操作完成之后继续执行该进程。
随着计算机硬件和软件的发展,多任务操作系统应运而生。在进程调度程序的协助下,多任务操作系统一次性可以加载多个进程,并将 CPU 资源合理地分配给它们。仍以当前进程正在进行 I/O 操作为例,进程调度程序会从处于就绪状态的诸多进程中挑选出一个进程,然后将 CPU 资源分配给它。
所谓进程调度,是指根据既定规则挑选一个处于就绪状态的进程并将 CPU 资源分配给它的过程。多任务操作系统中,进程调度由特定的进程调度程序(或者称为进程调度器)负责。借助进程调度程序,多任务操作系统极大提高了 CPU 的利用率。
进程调度是多任务操作系统的重要组成部分,您也可以这样理解,正是由于进程调度程序的引入,才使得操作系统具备了“多任务”的能力。
进程调度队列
《进程控制块(PCB)是什么》一节提到,多任务操作系统(后续简称操作系统)借助 PCB 管理和控制所有进程。
首先,操作系统会将所有进程的 PCB 统一组织到一个队列中,通常称为作业队列。
操作系统还为每种状态的进程单独维护一个队列,将处于相同状态的进程的 PCB 组织到同一队列中。例如,操作系统会把位于内存中的、处于就绪状态的所有进程的 PCB 组织到就绪队列中。
注意,同一时刻处于运行状态的进程只能有 1 个,因此运行队列中最终只包含一个进程的 PCB。
此外,每个 I/O 设备都各自配有一个队列,统称为设备队列。假设当前进程向某个 I/O 设备发送 I/O 请求,但此时该设备正忙于处理先前进程发出的 I/O 请求,因此当前进程不得不等待。这种情况下,该进程的 PCB 就会由运行队列转入此 I/O 设备的设备队列。
当进程状态发生转变时,它的 PCB 也会移动至相应状态的队列中。操作系统负责维护和管理这些队列,而进程调度程序负责将 CPU 资源调度给处于就绪状态的某个进程。
进程调度程序的种类
进程的整个生命周期中,其对应的 PCB 会在各种调度队列中迁移,因此操作系统必须制定一套完整的进程调度机制。
进程调度程序又称进程调度器,是一种特殊的系统软件,它的主要任务是合理调度操作系统中的进程,使系统能够平稳、顺畅地运行。
不同的操作系统中,进程调度程序也略有差异。一套完整的进程调度机制,可能需要 3 种调度程序相互配合完成,分别称为长期调度程序、短期调度程序和中期调度程序。
1) 长期调度程序
某些操作系统(例如多道批处理系统)中,用户提交的任务量可能远远超过系统可以同时执行的最大进程数,为了控制内存中的进程数量,操作系统会将部分任务存储在外部存储器(通常是硬盘)中,同时建立一种调度机制,以便适当时候还能将外存中的任务移到内存。
长期调度程序又称作业调度程序,它用于从外部存储器中挑选符合条件的任务(或者称作业),并将其移入内存等待分配 CPU 资源。
长期调度程序负责维护操作系统的平稳运行,具体体现在以下两个方面:
- 保持系统中的进程数量趋于稳定,最理想的情况是:创建进程的平均速度等于进程消亡的平均速度;
- 确保计算机的各种资源都能得到充分利用,长期调度程序从外存选择任务时,通常会采取 I/O 密集型任务和 CPU 密集型任务混合调度的方式。
I/O 密集型任务指的是花费大量时间进行 I/O 操作的任务;CPU 密集型任务指的是花费大部分时间使用 CPU 的任务。
注意,并非所有的操作系统中都包含长期调度程序,Unix 和 Windows 分时系统通常没有长期调度程度,它们将所有进程都存放在内存中。
2) 短期调度程序
我们通常所说的进程调度程序,其实指的是短期调度程序,它可以从位于内存的就绪队列中选择一个合适的进程,并将 CPU 资源分配给它。
也就是说,短期调度程序决定着 CPU 下一步要执行哪个进程。
3) 中期调度程序
中期调度程序的主要功能是将暂时未执行的进程从内存移到外部存储器(通常是硬盘),为其它进程腾出内存空间,一段时间后再将其移入内存。
假设某个进程的 PCB 位于某个设备队列中,短时间内无法完成 I/O 操作。这种情况下,中期调度程序就可能将其从内存移到外存,一段时间后再移入内存(此过程常称为交换)。
注意,中期调度程序在将进程移出内存的时候,会将进程状态保存到 PCB 中。这样当进程再次引入内存时,就可以恢复它先前的执行状态使其继续执行。
和长期调度程序类似,并非所有的操作系统都包含中期调度程序,有些分时操作系统可能会包含中期调度程序。
下图为您演示了以上 3 种调度程序各自的功能:
图 1 3 种调度程序各自的功能
进程上下文切换
所谓进程的上下文切换,指的是将 CPU 资源从一个进程移交给另一个进程的过程。
整个进程上下文切换的过程,包含以下两项工作:
- 将前一个进程的执行状态保存到它的 PCB 中,以便将来可以恢复该进程的执行;
- 根据将要执行进程的 PCB 中存储的信息,还原该进程的执行状态,使其继续执行。
操作系统中,进程上下文切换的工作也由进程调度程序来完成,更确切地说,是由短期调度程序来完成。
进程上下文切换的整个过程,会涉及到对很多寄存器和存储器中数据的保存和恢复,需要经过大量的计算。此外,进程上下文切换所花费的时间受计算机硬件的影响较大。通常情况下,进程上下文切换的过程可以在几毫秒内完成。
进程上下文切换的过程中,操作系统只能等待,因此整个切换过程所花费的时间属于纯系统开销,无法被有效利用。