1. 程序执行
1.1. 顺序执行
程序就是一个指令序列,通常一个应用程序由若干个程序段组成,每一个程序段完成特定的功能,它们在行时都需要按照某种先后次序顺序执行。例如在进行计算时,应先运行输入程序获取用户的输入,然后运行计算程序进行计算,最后输出计算结果。用结点代表各程序段的操作,其中 I 代表输入操作,C 代表计算操作,P 为打印操作。
程序的顺序执行在内存中仅装入一道用户程序,该程序独占系统中的所有资源。只有在一个用户程序执行完成后,才允许装入另一个程序并执行,因此这种方式浪费资源、系统运行效率低。不过这种方式具有可再现性,也就是只要程序执行时的环境和初始条件相同,当程序重复执行时可获得相同的结果,这种特性利于开发人员进行调试。
1.2. 并发执行
观察上面的图,执行一次计算操作需要借助 3 类资源:输入设备、CPU 和输出设备,注意当 C1 被执行的时候输入设备是空闲的。如果在执行 C1 时让输入设备执行 I2,这样当 C1 执行完毕后就可以继续执行 C2。以此类推可以发现这么做可以有效利用资源,提高系统的运行效率,这就是程序的并发执行。
程序并发执行虽然提高了系统的吞吐量和资源利用率,但由于它们共享系统资源,致使在这些并发执行的程序之间必将形成相互制约的关系。例如当计算程序完成 C1 的计算后,如果输入程序 I1 尚未完成,则计算程序 C2 就无法进行计算。同时程序在并发执行时失去了封闭性,也将导致其又失去可再现性。
(1)间断性
(2)失去封闭性
(3)不可再现性
2. 进程
2.1. 进程的定义
为了使参与并发执行的每个程序(含数据)都能独立地运行,操作系统中为之配置一个专门的数据结构——进程控制块(Process Control Block,PCB)用来描述进程的基本情况和活动过程。由程序段、相关的数据段和 PCB 三部分便构成了进程实体(又称进程映像),一般情况下把进程实体就简称为进程。
进程是进程实体的运行过程,是系统进行资源分配和调度的一个独立单位。引入了“进程”的概念能使程序并发执行,并且可以对并发执行的程序加以描述和控制。进程具有的一些特性如下:
- 动态性:进程的实质是进程实体的执行过程;
- 并发性:多个进程实体同存于内存中,且能在一段时间内同时运行;
- 独立性:进程实体是一个能独立运行、独立获得资源和独立接受调度的基本单位;
- 异步性:进程是按各自独立的、不可预知的速度向前推进;
结构性:每个进程都需要配置一个名为 PCB 的数据结构。2.2. 与作业的区别
作业是用户需要计算机完成某些任务的工作集合,是用户向计算机提交的任务实体,作业的概念主要用于批处理系统中。进程是已经提交的作业的执行过程,是资源分配的基本单位,几乎存在于所有多道程序系统中。一个作业可以由多个进程组成,至少是一个进程,但是一个进程不能构成多个作业。2.3. 进程的状态
由于多个进程在并发执行时呈现间断性的运行规律,所以进程在其生命周期内可能具有多种状态。
状态 | 说明 |
---|---|
就绪(Ready)状态 | 进程已分配到除 CPU 以外的所有必要资源,只要再获得 CPU 便可立即执行 |
执行(Running)状态 | 进程已获得 CPU,其程序正在执行的状态 |
阻塞(Block)状态 | 正在执行的进程由于发生某事件(如I/O请求、申请缓冲区失败等)暂时无法继续执行时的状态 |
创建状态 | 进程所需的资源尚不能得到满足,还在创建当中的状态 |
终止状态 | 等待操作系统进行善后处理,后将 PCB 清零并返还空间的状态 |
其中对于进程的创建,首先要申请一个空白 PCB 并填写用于控制和管理进程的信息,然后为该进程分配运行时所必须的资源,最后把该进程转入就绪状态并插入就绪队列之中。如果进程创建工作尚未完成,进程不能被调度运行时,该进程就属于创建状态。进程各状态的转换关系如下:
2.4. 挂起操作
挂起操作作用于某个进程时,被挂起的进程将处于静止状态,只有对该进程进行激活操作才能恢复。如果进程正在执行将被暂停,如果处于就绪状态则该进程此时暂不接受调度。
挂起操作可以应用于如下的场景:
场景 | 说明 |
---|---|
终端用户的需要 | 在程序运行期间发现有可疑问题,希望暂停程序的运行进行修改 |
父进程请求 | 父进程希望挂起自己的某个子进程进行修改或协调 |
负荷调节的需要 | 系统中的工作负荷较重,可由系统把一些不重要的进程挂起 |
操作系统的需要 | 操作系统通过挂起来检查运行中的资源使用情况或进行记账 |
3. 进程控制块
3.1. 资源信息表
OS 对于每个资源和每个进程都设置了一个数据结构来表征其实体,通常称这个数据结构为资源信息表或进程信息表,其中包含了资源或进程的标识、描述、状态等信息以及一批指针。通过这些指针可以将同类资源或进程的信息表,或者同一进程所占用的资源信息表分类链接成不同的队列,通常有内存表、设备表、文件表和进程表。
3.2. 进程控制块
进程控制块 PCB(Process Control Block)作为进程实体的一部分,记录了操作系统所需的,用于描述进程的当前情况以及管理进程运行的全部信息。
PCB 的作用有:
- 作为独立运行的基本单位的标志:使一个在多道程序环境下,使不能独立运行的程序(含数据)成为一个能独立运行的基本单位;
- 能实现间断性运行方式:当进程因阻塞而暂停运行时,系统就可将 CPU 现场信息保存在被中断进程的 PCB 中,供该进程再次被调度执行时恢复 CPU 现场时使用;
- 提供进程管理所需要的信息:当调度程序调度到某进程运行时,通过 PCB 中记录的程序和数据在内存或外存中的始址指针找到相应的程序和数据;
- 提供进程调度所需要的信息:PCB 中就提供了进程处于何种状态的信息;
- 实现与其它进程的同步与通信:在 PCB 中还具有用于实现进程通信的区域或通信队列指针等。
3.3. PCB 中的信息
进程标识符
进程标识符用于唯一地标识一个进程,通常有两种标识符:
信息 | 说明 |
---|---|
外部标识符 | 方便用户(进程)对进程的访问而设置的外部标识符 |
内部标识符 | 方便系统对进程的使用而设置了内部标识符 |
处理机状态
处理机状态信息也称为处理机的上下文,主要是由处理机的各种寄存器中的内容组成的,包括:
信息 | 说明 |
---|---|
通用寄存器 | 用户程序可以访问的寄存器,用于暂存信息 |
指令计数器 | 其中存放了要访问的下一条指令的地址 |
程序状态字 PSW | 含有状态信息,如条件码、执行方式、中断屏蔽标志等 |
用户栈指针 | 用于存放过程和系统调用参数及调用地址。栈指针指向该栈的栈顶 |
进程调度信息
在 OS 进行调度时必须了解进程的状态及有关进程调度的信息,这些信息包括:
信息 | 说明 |
---|---|
进程状态 | 指明进程的当前状态 |
进程优先级 | 用于描述进程使用处理机的优先级别的一个整数 |
进程调度所需的其它信息 | 和采用的调度算法有关 |
事件 | 进程由执行状态转变为阻塞状态所等待发生的事件 |
进程控制信息
用于进程控制所必须的信息,包括:
信息 | 说明 |
---|---|
程序和数据的地址 | 进程实体中的程序和数据的内存或外存地(首)址 |
进程同步和通信机制 | 如消息队列指针、信号量等 |
资源清单 | 进程在运行期间所需的全部资源和已分配的资源的清单 |
链接指针 | 本进程所在队列中的下一个进程的 PCB 的首地址 |
3.4. PCB 的组织方式
在一个系统中通常会拥有一对 PCB。为了能对它们加以有效的管理,应该用适当的方式将这些 PCB 组织起来。
第一种是线性方式,将系统中所有的 PCB 都组织在一张线性表中,将该表的首址存放在内存的一个专用区域中。该方式实现简单、开销小,但每次查找时都需要扫描整张表。
第二种是链接方式,把具有相同状态进程的 PCB 分别通过 PCB 中的链接字链接成一个队列,可以形成就绪队列、若干个阻塞队列和空白队列等,操作系统持有指向各个队列的指针。
第三种是索引方式,即系统根据所有进程状态的不同建立索引表,并把各索引表在内存的首地址记录在内存的一些专用单元中。
4. 进程控制
进程控制是进程管理中最基本的功能,主要包括创建新进程、终止已完成的进程、将因发生异常情况而无法继续运行的进程置于阻塞状态、负责进程运行中的状态转换等功能。
4.1. 创建进程
为使程序之间能并发运行,应先为它们分别创建进程,创建进程的一些事件例如:
事件 | 说明 |
---|---|
用户登录 | 用户若登录成功,系统将为该用户建立一个进程 |
作业调度 | 当作业调度程序按一定的算法调度到某个(些)作业时,便将它装入内存创建进程 |
提供服务 | 系统专门创建一个进程来提供用户所需要的服务 |
应用请求 | 用户进程自己创建新进程来完成一些特点的功能 |
在系统中每当出现了创建新进程的请求后,OS 便调用进程创建原语 Creat 按下述步骤创建一个新进程:
- 申请空白 PCB,为新进程申请唯一的数字标识符和一个空白 PCB;
- 为新进程分配其运行所需的资源,包括各种物理和逻辑资源,如内存、文件、I/O 设备和 CPU 时间等;
- 初始化 PCB:初始化标识信息、处理机状态信息和处理机控制信息;
- 将新进程插入就绪队列。
4.2. 进程的终止
当进程结束时需要终止进程,将该进程占有的资源释放掉,引起进程终止的事件有:
事件 | 说明 |
---|---|
正常结束 | 进程的任务已经完成,准备退出运行 |
异常结束 | 进程在运行时发生了某种异常事件,使程序无法继续运行 |
外界干预 | 进程应外界的请求而终止运行 |
如果系统中发生了要求终止进程的某事件,OS 便调用进程终止原语终止指定的进程:
- 根据被终止进程的标识符,从 PCB 集合中检索出该进程的 PCB,从中读出该进程的状态;
- 若被终止进程正处于执行状态,应立即终止该进程的执行,并置调度标志为真;
- 若该进程还有子孙进程,将其所有子孙进程也都终止;
- 将被终止进程所拥有的全部资源或者归还给其父进程或系统;
- 将被 PCB 从所在队列中移出。
4.3. 进程阻塞和唤醒
有下述几类事件会引起进程阻塞或被唤醒:
事件 | 说明 |
---|---|
向系统请求共享资源失败 | 系统没有足够的资源,进程因不能继续运行而转变为阻塞状态 |
等待某种操作的完成 | 如果进程必须在某个操作完成之后才能继续执行,则需要将该进程先阻塞 |
新数据尚未到达 | 如果一个进程需要先获得另一进程提供的数据,只要其所需数据尚未到达进程就要先阻塞 |
等待新任务的到达 | 一些进程完成任务后会阻塞自己,等待新任务的到来 |
正在执行的进程如果发生了上述某事件,进程便通过调用阻塞原语 block 主动将自己阻塞。阻塞后由于该进程还处于执行状态,所以应先立即停止执行,把进程控制块中的状态改为阻塞,再将 PCB 插入阻塞队列。当被阻塞进程需要被唤醒时,则由有关进程调用唤醒原语 wakeup将进程唤醒。wakeup 首先把被阻塞的进程从等待该事件的阻塞队列中移出,将其 PCB 中的现行状态由阻塞改为就绪,然后再将该 PCB 插入到就绪队列中。
4.4. 进程的挂起和激活
当系统中出现了引起进程挂起的事件时,OS 将利用挂起原语 suspend 将指定进程或处于阻塞状态的进程挂起。suspend 原语首先检查被挂起进程的状态,若处于活动就绪状态就改为静止就绪,若处于活动阻塞状态就改为静止阻塞,若被挂起的进程正在执行则转向调度程序重新调度。
当系统中发生激活进程的事件时,OS 将利用激活原语 active 将指定进程激活。激活原语先将进程从外存调入内存,检查该进程的现行状态,若是静止就绪就改为活动就绪,若为静止阻塞就改为活动阻塞。
5. 进程通信
进程通信指的是进程之间的信息交换,进程间要传送大量数据往往需要利用 OS 提供的高级通信工具。
5.1. 共享存储器系统
在共享存储器系统中,进程通过一些共享的数据结构或共享存储区进行通信,两个通信的进程对共享空间的访问必须是互斥的。共享存储器系统分成以下两种类型:
- 共享数据结构:进程公用某些数据结构实现信息交换,这种方式仅适于传递相对少量的数据,通信效率低下。
- 共享存储区:内存中划出了一块共享存储区域,进程通过对该共享区的读或写交换信息实现通信。
5.2. 管道通信系统
管道指开辟一个固定大小的缓冲区,用于连接一个读进程和一个写进程以实现通信。这种通信的方式是半双工的,开辟的缓冲区文件又名 pipe 文件。写进程)以字符流形式将大量的数据送入管道。而接受管道输出的接收进程(即读进程)则从管道中接收(读)数据。管道机制必须提供以下三方面的协调能力:
- 互斥:一个进程正在对 pipe 执行读/写操作时,其它(另一)进程必须等待;
- 同步:pipe 没有写满就不允许读取,没有读取完成就不允许写数据;
- 确定对方是否存在,只有确定了对方已存在时才能进行通信。
例如 Linux 系统下管道符“|”可以像一个管道一样传递数据,格式为“命令 A | 命令 B”,作用是把前一个命令的输出数据输入给后一个命令作为其输入。
Copy Highlighter-hljsls -l /etc/ | more
5.3. 消息传递系统(Message passing system)
进程不必借助任何共享存储区或数据结构,而是以格式化的消息(消息头 + 消息体)为单位,将通信的数据封装在消息中,并利用操作系统提供的一组通信命令(原语),在进程间进行消息传递。基于消息传递系统的通信方式可进一步分成两类:
- 直接通信方式,发送进程直接把消息发送给目标进程;
- 间接通信方式,是指发送和接收进程,都通过共享中间实体(称为邮箱)的方式进行消息的发送和接收。