2. 特权指令与非特权指令

2026 旧版 · 非 2027 主源 · 原书检索 · 文字用于定位,公式与图表请回原页核验 · 本次导入快照

## 2. 特权指令与非特权指令

特权指令是指有特殊权限的指令,由于这类指令的权限最大,使用不当将导致整个系统崩溃,如清内存、置时钟、分配系统资源、修改虚存的段表或页表、修改用户的访问权限等。若所有程序都能使用这些指令,则系统一天死机 $n$ 次就不足为奇。为保证系统安全,这类指令不能直接提供给用户使用,因此特权指令必须在内核态执行。实际上,CPU在内核态下可以执行指令系统的全集。形象地说,特权指令是那些儿童不宜的东西,而非特权指令是老少皆宜的东西。

为了防止用户程序中使用特权指令,用户态下只能使用非特权指令,内核态下可以使用全部指令。在用户态下使用特权指令时,将产生中断以阻止用户使用特权指令。所以将用户程序放在用户态下运行,而操作系统中必须使用特权指令的那部分程序在内核态下运行,从而保证了系统的安全性和可靠性。从用户态转换为内核态的唯一途径是中断或异常。

## 3. 访管指令与访管中断

访管指令(trap 指令)是一条在用户态下执行的指令。在用户程序中,因要求操作系统提供服务而有意识地使用访管指令,从而产生一个中断事件(自愿中断),将操作系统转换为内核态,称为访管中断。访管中断由访管指令产生,程序员使用访管指令向操作系统请求服务。

为什么要在程序中引入访管指令呢?这是因为用户程序只能在用户态下运行。若用户程序想要完成在用户态下无法完成的工作,该怎么办?解决这个问题要靠访管指令。访管指令本身不是特权指令,其基本功能是让程序拥有“自愿进管”的手段,从而引起访管中断。

## 4. 定义微内核结构OS的四个方面

1)足够小的内核。
2)基于客户/服务器模式。
3)应用“机制与策略分离”原理。机制是指实现某一功能的具体执行机构。策略则是在机制的基础上借助于某些参数和算法来实现该功能的优化,或达到不同的功能目标。在传统的OS中,将机制放在OS内核的较低层中,将策略放在内核的较高层中。而在微内核OS中,通常将机制放在OS的微内核中。正因如此,才可以将内核做得很小。
4)采用面向对象技术。基于面向对象技术中的“抽象”和“隐蔽”原则能控制系统的复杂性,进一步利用“对象”“封装”和“继承”等概念还能确保操作系统的正确性、可靠性、易扩展性等。正因如此,面向对象技术被广泛应用于现代操作系统的设计之中。


<!-- page: 48 -->

# 进程与线程

## 【考纲内容】

(一)进程与线程

进程与线程的基本概念;进程/线程的状态与转换

线程的实现:内核支持的线程,线程库支持的线程

进程与线程的组织与控制

进程间通信:共享内存,消息传递,管道,信号

(二)CPU调度与上下文切换

调度的基本概念;调度的目标;

调度的实现:调度器/调度程序(scheduler),调度的时机与调度方式(抢占式/非抢占式),闲逛进程,内核级线程与用户级线程调度

CPU调度算法

多处理机调度

上下文及其切换机制

(三)同步与互斥

同步与互斥的基本概念

基本的实现方法:软件方法;硬件方法

锁;信号量;条件变量

经典同步问题:生产者-消费者问题,读者-写者问题;哲学家进餐问题

(四)死锁

死锁的基本概念;死锁预防

死锁避免;死锁检测和解除

## 【复习提示】

进程管理是操作系统的核心,也是每年必考的重点。其中,进程的概念、进程调度、信号量机制实现同步和互斥、进程死锁等更是重中之重,必须深入掌握。需要注意的是,除选择题外,本章还容易出综合题,其中信号量机制实现同步和互斥、进程调度算法和死锁等都可能命制综合题,如利用信号量进行进程同步就在往年的统考中频繁出现。

视频讲解

## 2.1 进程与线程

在学习本节时,请读者思考以下问题:

1)为什么要引入进程?
2)什么是进程?进程由什么组成?


<!-- page: 49 -->

3)进程是如何解决问题的?

希望读者带着上述问题去学习本节内容,并在学习的过程中多思考,从而更深入地理解本节内容。进程本身是一个比较抽象的概念,它不是实物,看不见、摸不着,初学者在理解进程概念时存在一定困难,在介绍完进程的相关知识后,我们会用比较直观的例子帮助大家理解。

## 2.1.1 进程的概念和特征

### 1. 进程的概念

在多道程序环境下,允许多个程序并发执行,此时它们将失去封闭性,并具有间断性及不可再现性的特征。为此引入了进程(Process)的概念,以便更好地描述和控制程序的并发执行,实现操作系统的并发性和共享性(最基本的两个特性)。

为了使参与并发执行的每个程序(含数据)都能独立地运行,必须为之配置一个专门的数据结构,称为进程控制块(Process Control Block,PCB)。系统利用PCB来描述进程的基本情况和运行状态,进而控制和管理进程。相应地,由程序段、相关数据段和PCB三部分构成了进程实体(也称进程映像)。所谓创建进程,就是创建进程的PCB;而撤销进程,就是撤销进程的PCB。

从不同的角度,进程可以有不同的定义,比较典型的定义有:

1)进程是一个正在执行程序的实例。
2)进程是一个程序及其数据从磁盘加载到内存后,在CPU上的执行过程。
3)进程是一个具有独立功能的程序在一个数据集合上运行的过程。

引入进程实体的概念后,我们可将传统操作系统中的进程定义为:“进程是进程实体的运行过程,是系统进行资源分配和调度的一个独立单位。”

读者要准确理解这里说的系统资源。它指CPU、存储器和其他设备服务于某个进程的“时间”,例如将CPU资源理解为CPU的时间片才是准确的。因为进程是这些资源分配和调度的独立单位,即“时间片”分配的独立单位,这就决定了进程一定是一个动态的、过程性的概念。

### 2. 进程的特征

进程是由多道程序的并发执行而引出的,它和程序是两个截然不同的概念。程序是静态的,进程是动态的,进程的基本特征是对比单个程序的顺序执行提出的。

1)动态性。进程是程序的一次执行,它有着创建、活动、暂停、终止等过程,具有一定的生命周期,是动态地产生、变化和消亡的。动态性是进程最基本的特征。
2)并发性。指多个进程同存于内存中,能在一段时间内同时运行。引入进程的目的就是使进程能和其他进程并发执行。并发性是进程的重要特征,也是操作系统的重要特征。
3)独立性。指进程是一个能独立运行、独立获得资源和独立接受调度的基本单位。凡未建立PCB的程序,都不能作为一个独立的单位参与运行。
4)异步性。由于进程的相互制约,使得进程按各自独立的、不可预知的速度向前推进。异步性会导致执行结果的不可再现性,为此在操作系统中必须配置相应的进程同步机制。

通常不会直接考查进程有什么特性,所以读者对上面的4个特性不必记忆,只求理解。

## 2.1.2 进程的组成

进程是一个独立的运行单位,也是操作系统进行资源分配和调度的基本单位。它由以下三部分组成,其中最核心的是进程控制块(PCB)。

### 1. 进程控制块

进程创建时,操作系统为它新建一个PCB,该结构之后常驻内存,任意时刻都可以存取,并


<!-- page: 50 -->

在进程结束时删除。PCB 是进程实体的一部分,是进程存在的唯一标志。

进程执行时,系统通过其 PCB 了解进程的现行状态信息,以便操作系统对其进行控制和管理;进程结束时,系统收回其 PCB,该进程随之消亡。

当操作系统希望调度某个进程运行时,要从该进程的 PCB 中查出其现行状态及优先级;在调度到某个进程后,要根据其 PCB 中所保存的 CPU 状态信息,设置该进程恢复运行的现场,并根据其 PCB 中的程序和数据的内存始址,找到其程序和数据;进程在运行过程中,当需要和与之合作的进程实现同步、通信或访问文件时,也需要访问 PCB;当进程由于某种原因此暂停运行时,又需将其断点的 CPU 环境保存在 PCB 中。可见,在进程的整个生命期中,系统总是通过 PCB 对进程进行控制的,亦即系统唯有通过进程的 PCB 才能感知到该进程的存在。

表 2.1 是一个 PCB 的实例。PCB 主要包括进程描述信息、进程控制和管理信息、资源分配清单和 CPU 相关信息等。各部分的主要说明如下:

表 2.1 PCB 通常包含的内容

[tbl-0.md](tbl-0.md)

1)进程描述信息。进程标识符:标志各个进程,每个进程都有一个唯一的标识号。用户标识符:进程所归属的用户,用户标识符主要为共享和保护服务。

2)进程控制和管理信息。进程当前状态:描述进程的状态信息,作为 CPU 分配调度的依据。进程优先级:描述进程抢占 CPU 的优先级,优先级高的进程可优先获得 CPU。

3)资源分配清单,用于说明有关内存地址空间或虚拟地址空间的状况,所打开文件的列表和所使用的输入/输出设备信息。

4)处理机相关信息,也称 CPU 上下文,主要指 CPU 中各寄存器的值。当进程处于执行态时,CPU 的许多信息都在寄存器中。当进程被切换时,CPU 状态信息都必须保存在相应的 PCB 中,以便在该进程重新执行时,能从断点继续执行。

在一个系统中,通常存在着许多进程的 PCB,有的处于就绪态,有的处于阻塞态,而且阻塞的原因各不相同。为了方便进程的调度和管理,需要将各个进程的 PCB 用适当的方法组织起来。目前,常用的组织方式有链接方式和索引方式两种。链接方式将同一状态的 PCB 链接成一个队列,不同状态对应不同的队列,也可将处于阻塞态的进程的 PCB,根据其阻塞原因的不同,排成多个阻塞队列。索引方式将同一状态的进程组织在一个索引表中,索引表的表项指向相应的 PCB,不同状态对应不同的索引表,如就绪索引表和阻塞索引表等。

2. 程序段

程序段就是能被进程调度程序调度到 CPU 执行的程序代码段。注意,程序可被多个进程共享,即多个进程可以运行同一个程序。公众号:小兔网盘 免费分享无水印PDF

3. 数据段

一个进程的数据段,可以是进程对应的程序加工处理的原始数据,也可以是程序执行时产生


<!-- page: 51 -->

的中间或最终结果。

## 2.1.3 进程的状态与转换

进程在其生命周期内,由于系统中各个进程之间的相互制约及系统的运行环境的变化,使得进程的状态也在不断地发生变化。通常进程有以下5种状态,前3种是进程的基本状态。

1)运行态。进程正在CPU上运行。在单CPU中,每个时刻只有一个进程处于运行态。
2)就绪态。进程获得了除CPU外的一切所需资源,一旦得到CPU,便可立即运行。系统中处于就绪态的进程可能有多个,通常将它们排成一个队列,称为就绪队列。

### 创建系统
**执行中断处理程序时进程的状态(2023)**

3)组塞态,也称等待态。进程正在等待某一事件而暂停运行,如等待某个资源可用(不包括CPU)或等待I/O完成。即使CPU空闲,该进程也不能运行。系统通常将处于阻塞态的进程也排成一个队列,甚至根据阻塞原因的不同,设置多个阻塞队列。
4)创建态。进程正在被创建,尚未转到就绪态。创建进程需要多个步骤:首先申请一个空白PCB,并向PCB中填写用于控制和管理进程的信息;然后为该进程分配运行时所必须的资源;最后将该进程转入就绪态并插入就绪队列。但是,若进程所需的资源尚不能得到满足,如内存不足,则创建工作尚未完成,进程此时所处的状态称为创建态。
5)终止态。进程正从系统中消失,可能是进程正常结束或其他原因退出运行。进程需要结束运行时,系统首先将该进程置为终止态,然后进一步处理资源释放和回收等工作。

**区分就绪态和阻塞态**:就绪态是指进程仅缺少CPU,只要获得CPU就立即运行;而阻塞态是指进程需要其他资源(除了CPU)或等待某一事件。之所以将CPU和其他资源分开,是因为在分时系统的时间片轮转机制中,每个进程分到的时间片是若干毫秒。也就是说,进程得到CPU的时间很短且非常频繁,进程在运行过程中实际上是频繁地转换到就绪态的;而其他资源(如外设)的使用和分配或某一事件的发生(如I/O完成)对应的时间相对来说很长,进程转换到阻塞态的次数也相对较少。这样来看,就绪态和阻塞态是进程生命周期中两个完全不同的状态。

### 创建思路
**引起进程状态转换的事件(2014、2015、2018、2023)**

图2.1说明了5种进程状态的转换,而3种基本状态之间的转换如下:

- 就绪态 → 运行态:处于就绪态的进程被调度后,获得CPU资源(分派CPU的时间片),于是进程由就绪态转换为运行态。
- 运行态 → 就绪态:处于运行态的进程在时间片用完后,不得不让出CPU,从而进程由运行态转换为就绪态。此外,在可剥夺的操作系统中,当有更高优先级的进程就绪时,调度程序将正在执行的进程转换为就绪态,让更高优先级的进程执行。
- 运行态 → 组塞态:进程请求某一资源(如外设)的使用和分配或等待某一事件的发生(如I/O操作的完成)时,它就从运行态转换为阻塞态。进程以系统调用的形式请求操作系统提供服务,这是一种特殊的、由运行用户态程序调用操作系统内核过程的形式。

图2.1 5种进程状态的转换


<!-- page: 52 -->

- 阻塞态 → 就绪态:进程等待的事件到来时,如 I/O 操作完成或中断结束时,中断处理程序必须将相应进程的状态由阻塞态转换为就绪态。

需要注意的是,一个进程从运行态变为阻塞态是主动的行为,而从阻塞态变为就绪态是被动的行为,需要其他相关进程的协助。

## 2.1.4 进程控制

进程控制的主要功能是对系统中的所有进程实施有效的管理,它具有创建新进程、撤销已有进程、实现进程状态转换等功能。在操作系统中,一般将进程控制用的程序段称为原语,原语的特点是执行期间不允许中断,它是一个不可分割的基本单位。

### 1. 进程的创建

**创建通知** ▶ 父进程与子进程的关系和特点(2020、2024)

允许一个进程创建另一个进程,此时创建者称为父进程,被创建的进程称为子进程。子进程可以继承父进程所拥有的资源。当子进程终止时,应将其从父进程那里获得的资源还给父进程。

**创建通知** ▶ 导致创建进程的操作(2010)

在操作系统中,终端用户登录系统、作业调度、系统提供服务、用户程序的应用请求等都会引起进程的创建。操作系统创建一个新进程的过程如下(创建原语):

**创建通知** ▶ 创建新进程时的操作(2021)

1)为新进程分配一个唯一的进程标识号,并申请一个空白 PCB(PCB 是有限的)。若 PCB 申请失败,则创建失败。

2)为进程分配其运行所需的资源,如内存、文件、I/O 设备和 CPU 时间等(在 PCB 中体现)。这些资源或从操作系统获得,或仅从其父进程获得。若资源不足(如内存),则并不是创建失败,而是处于创建态,等待内存资源。

3)初始化 PCB,主要包括初始化标志信息、初始化 CPU 状态信息和初始化 CPU 控制信息,以及设置进程的优先级等。

4)若进程就绪队列能够接纳新进程,则将新进程插入就绪队列,等待被调度运行。

### 2. 进程的终止

引起进程终止的事件主要有:①正常结束,表示进程的任务已完成并准备退出运行。②异常结束,表示进程在运行时,发生了某种异常事件,使程序无法继续运行,如存储区越界、保护错、非法指令、特权指令错、运行超时、算术运算错、I/O 故障等。③外界干预,指进程应外界的请求而终止运行,如操作员或操作系统干预、父进程请求和父进程终止。

**创建通知** ▶ 终止进程时的操作(2024)

操作系统终止进程的过程如下(终止原语):

1)根据被终止进程的标识符,检索出该进程的 PCB,从中读出该进程的状态。

2)若被终止进程处于运行状态,立即终止该进程的执行,将 CPU 资源分配给其他进程。

3)若该进程还有子孙进程,则通常需将其所有子孙进程终止(有些系统无此要求)。

4)将该进程所拥有的全部资源,或归还给其父进程,或归还给操作系统。

5)将该 PCB 从所在队列(链表)中删除。

有些系统不允许子进程在父进程终止的情况下存在,对于这类系统,若一个进程终止,则它的所有子进程也终止,这种现象称为级联终止。然而,不是所有操作系统都是这么设计的。


<!-- page: 53 -->

## 3. 进程的阻塞和唤醒

**简题连接** ▶ I/O事件阻塞或唤醒进程的过程(2023)

**简题连接** ▶ 进程阻塞的事件与时机(2018、2022、2023)

正在执行的进程,由于期待的某些事件未发生,如请求系统资源失败、等待某种操作的完成、新数据尚未到达或无新任务可做等,进程便通过调用阻塞原语(Block),使自己由运行态变为阻塞态。可见,阻塞是进程自身的一种主动行为,也因此只有处于运行态的进程(获得CPU),才可能将其转为阻塞态。阻塞原语的执行过程如下:

1)找到将要被阻塞进程的标识号(PID)对应的PCB。
2)若该进程为运行态,则保护其现场,将其状态转为阻塞态,停止运行。
3)将该PCB插入相应事件的等待队列,将CPU资源调度给其他就绪进程。

**简题连接** ▶ 进程唤醒的事件与时机(2014、2019)

当被阻塞进程所期待的事件出现时,如它所期待的I/O操作已完成或其所期待的数据已到达,由有关进程(比如,释放该I/O设备的进程,或提供数据的进程)调用唤醒原语(Wakeup),将等待该事件的进程唤醒。唤醒原语的执行过程如下:

1)在该事件的等待队列中找到相应进程的PCB。
2)将其从等待队列中移出,并置其状态为就绪态。
3)将该PCB插入就绪队列,等待调度程序调度。

应当注意,Block原语和Wakeup原语是一对作用刚好相反的原语,必须成对使用。若在某个进程中调用了Block原语,则必须在与之合作的或其他相关的进程中安排一条相应的Wakeup原语,以便唤醒阻塞进程;否则,阻塞进程将因不能被唤醒而永久地处于阻塞态。

## 2.1.5 进程的通信

进程通信是指进程之间的信息交换。PV操作(见2.3节)是低级通信方式,高级通信方式是指以较高的效率传输大量数据的通信方式。高级通信方法主要有以下三类。

### 1. 共享存储

在通信的进程之间存在一块可直接访问的共享空间,通过对这片共享空间进行读/写操作实现进程之间的信息交换,如图2.2所示。在对共享空间进行读/写操作时,需要使用同步互斥工具(如P操作、V操作)对共享空间的读/写进行控制。共享存储又分为两种:低级方式的共享是基于数据结构的共享;高级方式的共享则是基于存储区的共享。操作系统只负责为通信进程提供可共享使用的存储空间和同步互斥工具,而数据交换则由用户自己安排读/写指令完成。

注意,进程空间一般都是独立的,进程运行期间一般不能访问其他进程的空间,想让两个进程共享空间,必须通过特殊的系统调用实现,而进程内的线程是自然共享进程空间的。

简单理解就是,甲和乙中间有一个大布袋,甲和乙交换物品是通过大布袋进行的,甲将物品放在大布袋里,乙拿走。但乙不能直接到甲的手中拿东西,甲也不能直接到乙的手中拿东西。

### 2. 消息传递

若通信的进程之间不存在可直接访问的共享空间,则必须利用操作系统提供的消息传递方法实现进程通信。在消息传递系统中,进程间的数据交换以格式化的消息(Message)为单位。进程通过操作系统提供的发送消息和接收消息两个原语进行数据交换。这种方式隐藏了通信实现细节,使通信过程对用户透明,简化了通信程序的设计,是当前应用最广泛的进程间通信机制。在微内核操作系统中,微内核与服务器之间的通信就采用了消息传递机制。该机制能很好地支持多


<!-- page: 54 -->

CPU系统、分布式系统和计算机网络,因此也成为这些领域最主要的通信工具。

1)直接通信方式。发送进程直接将消息发送给接收进程,并将它挂在接收进程的消息缓冲队列上,接收进程从消息缓冲队列中取得消息,如图2.3所示。

图2.2 共享存储

图2.3 消息传递

2)间接通信方式。发送进程将消息发送到某个中间实体,接收进程从中间实体取得消息。这种中间实体一般称为信箱。该通信方式广泛应用于计算机网络中。

简单理解就是,甲要将某些事情告诉乙,就要写信,然后通过邮差送给乙。直接通信就是邮差将信直接送到乙的手上;间接通信就是乙家门口有一个邮箱,邮差将信放到邮箱里。

## 3. 管道通信

**前置通信** 管道通信的特点(2014)

管道是一个特殊的共享文件,也称pipe文件,数据在管道中是先进先出的。管道通信允许两个进程按生产者-消费者方式进行通信(见图2.4),只要管道不满,写进程就能向管道的一端写入数据;只要管道非空,读进程就能从管道的一端读出数据。为了协调双方的通信,管道机制必须提供三方面的协调能力:①互斥,指当一个进程对管道进行读/写操作时,其他进程必须等待。②同步,指写进程向管道写入一定数量的数据后,写进程阻塞,直到读进程取走数据后再将它唤醒;读进程将管道中的数据取空后,读进程阻塞,直到写进程将数据写入管道后才将其唤醒。③确定对方的存在。

图2.4 管道通信

在Linux中,管道是一种使用非常频繁的通信机制。从本质上说,管道也是一种文件,但它又和一般的文件有所不同,管道可以克服使用文件进行通信的两个问题,具体表现如下:

1)限制管道的大小。管道文件是一个固定大小的缓冲区,在Linux中该缓冲区的大小为4KB,这使得它的大小不像普通文件那样不加检验地增长。使用单个固定缓冲区也会带来问题,比如在写管道时可能变满,这种情况发生时,随后对管道的write()调用将默认地被阻塞,等待某些数据被读取,以便腾出足够的空间供write()调用。

2)读进程也可能工作得比写进程快。当管道内的数据已被读取时,管道变空。当这种情况发生时,一个随后的read()调用将被阻塞,等待某些数据的写入。

管道只能由创建进程所访问,当父进程创建一个管道后,管道是一种特殊文件,子进程会继承父进程的打开文件,因此子进程也继承父进程的管道,并可用它来与父进程进行通信。