Process and Scheduling(进程与调度策略)
文章目录
前言
通过上一章节操作系统的历史演进我们知道,为了提高资源利用率和系统吞吐量,人们发明了多道批处理操作系统,将多个程序同时装入内存,并使之并发运行,传统意义上的程序不再独立运行。此时,作为资源分配和独立运行的基本单位我们称之为进程(process)。在操作系统中,进程是非常重要的概念,可以说掌握了进程就掌握了操作系统的骨干。本章我们就对进程进行详细地说明。
一、程序并发执行 (Concurrency)
在早期的计算机包括单道批处理系统中,程序都是顺序执行的,即在一段时间内,该计算机的所有资源都被改程序所占有,如果改程序需要进行I/O操作,那么由于没有其他任务,CPU只能等待I/O操作完成再继续执行当前任务,这就造成了资源的浪费,系统运行效率不高。为了解决上述问题,后来人们引入了多道批处理系统,直接将多个程序装入到内存中,使他们共享资源,达到并发执行的目的。
这里我们区分一下并发和并行的区别。并行(Parallel)是指两个或多个事件在同一时刻发生。而并发(Concurrency)是指两个或多个事件在同一时间间隔内发生。在多道程序环境下,并发性是指在一段时间内宏观上有多个程序同时运行;但是在单处理机系统中,每一时刻只能有一道程序运行,因此在微观上来看,这些程序只能分时地交替执行。我们可以看一个例子,来更好地理解为什么多道系统能够提高系统效率,如下图:
我们可以分别计算一下在两个不同系统下,CPU利用率,设备1利用率和设备2的利用率,并比较他们之间的差异,结果如下表:
我们不难发现,在多道程序系统下,无论是CPU利用率还是设备利用率,都远远高于单道程序系统,这也说明了我们为什么要采取并发的方式执行程序。为了使程序能够并发执行,并且可以对并发执行的程序进行描述和控制,人们引入了“进程”的概念。
二、进程 (Process)
1. 进程控制块PCB (Process Control Block)
为了使参与并发执行的每个程序都能独立地运行,在操作系统中我们为每一个进程配备了一个专门的数据结构用来描述进程的基本情况和活动过程,进而控制和管理进程,这个数据结构被称为进程控制块PCB。由程序段、相关的数据段和PCB三部分就构成了进程实体,进程实体也被简称为进程。而创建进程,就是创建进程实体中的PCB;撤销进程,就是撤销进程实体中的PCB。
进程和程序是两种截然不同的概念,我们可以从进程的特征中探究这两者的区别:
Feature | Explanation |
---|---|
动态性 | 进程由创建而产生,由调度而执行,由撤销而消亡,进程实体是有一定的生命周期的;而程序只是一组有序指令的集合,其存放在寄存器中,本身是静态的。 |
并发性 | 多个进程实体同时存在于内存中,且在一段时间内同时运行,而程序是不能参与并发执行的。 |
独立性 | 进程实体是一个能独立运行、独立获得资源和接受独立调度的基本单位。 |
异步性 | 每个进程都按照各自独立的、不可预知的速度向前推进运行。 |
我们了解完PCB的性质之后,再来看一下PCB到底都储存有当前进程的那些信息。一般而言,PCB主要会存储当前进程的状态,下一个需要执行的指令的地址(PC), 该进程所需要的所有的寄存器,该进程的编号(PID)等。还有一些记录运行的内容,包括记录使用的CPU,从开始到现在运行的时间等。
2. 进程的状态和转换 (State and Shift)
一个任务要被CPU执行,必须创建相应的进程;此外,由于进程在并发执行时共享资源,导致它们在运行过程中呈现间断性地运行规律,因此,一个进程在其生命周期内具有多部不同的状态。而操作系统通过改变记录在PCB中该进程的状态信息可以方便地对进程状态进行切换操作。下面的示意图展示了 P 0 P_{0} P0和 P 1 P_{1} P1两个进程交替运行时操作系统对其PCB状态的切换过程:
(1). 进程的状态
一般而言,我们将进程分为五种状态:
[ 1 ] [1] [1] 创建状态(New):
创建一个进程的过程较为复杂,首先需要由进程申请一个空白的PCB,并向PCB中填写用于控制和管理进程的信息;然后为该进程分配运行时所需要的资源;最后,把该进程转为就绪状态并放入就绪队列之中。注意,如果进程所需要的资源得不到满足,那么该进程将会一直处在创建状态,直到其需要的资源得到满足。
[ 2 ] [2] [2] 就绪状态(Ready):
当进程处于就绪状态,这就表示进程已经拥有了除CPU之外的一切系统资源,一获得CPU资源,它便可以运行。如果系统中有很多就绪状态的进程,它们将会被放在就绪队列中,通常他们会按照一定的调度算法排成一个队列,我们在后边会详细介绍常见的进程调度算法。
[ 3 ] [3] [3] 运行状态(Running):
此时进程已经获得了CPU资源,正在被执行。
[ 4 ] [4] [4] 阻塞状态(Waiting):
当正在执行的进程由于某个事件,例如I/O请求,申请缓存区失败等,而暂时无法继续执行的时候,该进程的执行便受到了阻塞。此时会因此进程调度,操作系统会把处理机分配给下一个在就绪队列中等待的进程使用,而受阻塞的进程会被放在阻塞队列(等待队列)中,等待下一次被调用。
[ 5 ] [5] [5] 终止状态(Terminated):
当一个进程已经执行完了所有内容,或者出现了无法克服的错误时,该进程就会被操作系统所终止,其PCB里面的信息会被清空,清空后的PCB会被返回给系统。进入终止状态的进程不能够再被执行,但是操作系统仍然保留有一个记录,用来保存状态码和一些即使数据,以供其他进程所使用。
(2). 进程的切换
接下来我们深入代码层面,来看看进程之间到底是如何进行切换的。我们这里以一个进程要启动磁盘读写为例。代码如下:
pCur.state = 'WAIT';
wait_event