第二章 进程管理

本文详细介绍了操作系统中的进程管理,包括进程的概念、PCB、状态转换、进程控制原语、进程同步与通信。重点讲解了进程调度的基本概念、调度策略和典型调度算法,如FCFS、SJF、HRRN、时间片轮转等。此外,还深入探讨了线程的概念、多线程模型和死锁问题,阐述了死锁的预防、避免、检测和解除策略。
摘要由CSDN通过智能技术生成

文章目录

进程管理


1、进程与线程


1.1、进程的概念和特征


1、进程的概念

程序:是静态的,就是个存放在磁盘里的可执行文件,就是一系列的指令集合,如:QQ.exe。

进程(Process) :是动态的,是程序的一次执行过程,如可同时启动多次QQ程序。

同一个程序多次执行会对应多个进程

image-20220124011136236

2、进程的组成—PCB

思考:操作系统是这些进程的管理者,它要怎么区分各个进程?

当进程被创建时,操作系统会为该进程分配一个唯一的、不重复的“身份证号”—— PID (Process ID,进程ID)image-20220124012127713


PCB是进程存在的唯一标志,当进程被创建时,操作系统为其创建PCB,当进程结束时,会回收其PCB。

操作系统对进程进行管理工作所需的信息都存在PCB中。

image-20220124013336493


PCB是给操作系统用的

程序段、数据段给进程自己用的,与进程自身的运行逻辑有关。

程序段、数据段、PCB三部分组成了进程实体进程映像

引入进程实体的概念后,可把进程定义为:
进程是进程实体的运行过程,是系统进行资源分配调度的一个独立单位。

注意:PCB是进程存在的唯一标志!

3、进程的特征

程序是静态的,进程是动态的,相比于程序,进程拥有以下特征:image-20220124015621526

1.2、进程的状态与转换


1、进程的状态

创建状态:

进程正在被创建时,它的状态是“创建态”,在这个阶段操作系统会为进程分配资源、初始化PCB。

就绪状态:

当进程创建完成后,便进入“就绪态”,处于就绪态的进程已经具备运行条件,但由于没有空闲CPU,就暂时不能运行。

运行状态:

当CPU空闲时,操作系统就会选择一个就绪进程,让它上处理机运行。

如果一个进程此时在CPU上运行,那么这个进程处于“运行态”。
CPU会执行该进程对应的程序(执行指令序列)

阻塞状态:

在进程运行的过程中,可能会请求等待某个事件的发生(如等待某种系统资源的分配,或者等待其他进程的响应)。
在这个事件发生之前,进程无法继续往下执行,此时操作系统会让这个进程下CPU,并让它进入“阻塞态
当CPU空闲时,又会选择另一个“就绪态”进程上CPU运行。

当等待的事件发生时,进程“阻塞态“回到”就绪态“。

终止状态:

一个进程可以执行 exit系统调用,请求操作系统终止该进程。此时该进程会进入“终止态”,操作系统会让该进程下CPU,并回收内存空间等资源,最后还要回收该进程的PCB。当终止进程的工作完成之后,这个进程就彻底消失了。

image-20220124211147938

进程PCB中,会有一个变量state来表示进程的当前状态。如: 1表示创建态、2表示就绪态、3表示运行态…为了对同一个状态下的各个进程进行统一的管理,操作系统会将各个进程的PCB组织起来。


2、进程状态的转换

未命名文件

注意:不能由阻塞态直接转换为运行态,也不能由就绪态直接转换为阻塞态(因为进入阻塞态是进程主动请求的,必然需要进程在运行时才能发出这种请求)


1.3、进程控制

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

简化理解:反正进程控制就是要实现进程状态转换


1、如何实现进程控制?

用“原语”实现,原语的执行具有“原子性”,一气呵成。

思考:为何进程控制(状态转换)的过程要“一气呵成”?

image-20220124222828381

如果不能“一气呵成”,就有可能导致操作系统中的某些关键数据结构信息不统一的情况,这会影响操作系统进行别的管理工作。


2、如何实现原语的“原子性”?

原语的执行具有原子性,即执行过程只能一气呵成,期间不允许被中断
可以用“关中断指令”和“开中断指令”这两个特权指令实现原子性。

image-20220124224221920

3、进程控制相关的原语

(1)进程的创建

image-20220124225446365

(2)进程的终止

image-20220124225917280

(3)进程的阻塞和唤醒

image-20220124230258843

(4)进程的切换

image-20220124232249142

无论哪个进程控制原语,要做的无非三类事情:

1.更新PCB中的信息
2.将PCB插入合适的队列
3.分配/回收资源


1.4、进程的组织

image-20220124213720376

链接方式

image-20220124213851079

索引方式

image-20220124213924657


1.5、进程的通信


1、什么是进程通信?

顾名思义,进程通信就是指进程之间的信息交换。
进程是分配系统资源的单位(包括内存地址空间),因此各进程拥有的内存地址空间相互独立

image-20220124233623310


2、共享存储

image-20220125200559693


3、管道通信

image-20220125205219002


4、消息传递

进程间的数据交换以格式化的消息(Message)为单位。进程通过操作系统提供的“发送消息/接收消息”两个原语进行数据交换。

image-20220125210042385

直接通信方式

image-20220125210201740

间接通信方式

image-20220125210238731


1.6、线程概念和多线程模型


1、线程的基本概念

引入进程的目的是为了更好地使多道程序并发执行,提高资源利用率和系统吞吐量;而引入线程的目的则是为了减小程序在并发执行时所付出的时空开销,提高操作系统的并发性能

线程最直接的理解就是“轻量级进程”,它是一个基本的CPU执行单元,也是程序执行流的最小单元,由线程ID、程序计数器、寄存器集合和堆栈组成。线程是进程中的一个实体,是被系统独立调度和分派的基本单位,线程自己不拥有系统资源,只拥有一点儿在运行中必不可少的资源,但它可与同属一个进程的其他线程共享进程所拥有的全部资源。一个线程可以创建和撤销另一个线程,同一进程中的多个线程之间可以并发执行。由于线程之间的相互制约,致使线程在运行中呈现出间断性。线程也有就绪、阻塞和运行三种基本状态。

引入线程后,进程的内涵发生了改变,进程只作为除CPU外的系统资源的分配单元而线程则作为处理机的分配单元。由于一个进程内部有多个线程,若线程的切换发生在同一个进程内部,则只需要很少的时空开销。

image-20220125212552285


2、线程和进程的比较

image-20220125212852893


3、线程的属性

image-20220125213157264


4、线程的实现

线程的实现可以分为两类:用户级线程(User-Level Thread,ULT)和内核级线程(Kernel-Level Thread, KLT)。内核级线程又称内核支持的线程。

用户级线程

image-20220125222311072

内核级线程

image-20220125223121293


5、多线程模型

有些系统同时支持用户线程和内核线程,由此产生了不同的多线程模型,即实现用户级线程和内核级线程的连接方式

(1) 一对一模型

image-20220125223453682

(2) 多对一模型

image-20220125223741010

(3) 多对多模型

image-20220125225020228


1.7、本节知识框架图

进程


2、处理机调度


2.1、调度的概念


1、调度的基本概念

在多道程序系统中,进程的数量往往多于处理机的个数,因此进程争用处理机的情况在所难免。处理机调度是对处理机进行分配,即从就绪队列中按照一定的算法(公平、高效)选择一个进程并将处理机分配给它运行,以实现进程并发地执行。

image-20220125232440557


2、调度的层次

(1)高级调度

image-20220126120936731

高级调度(作业调度)。按一定的原则从外存的作业后备队列中挑选一个作业调入内存,并创建进程。**每个作业只调入一次,调出一次。**作业调入时会建立PCB,调出时才撤销PCB。

(2)低级调度

image-20220126121001252

低级调度(进程调度/处理机调度)――按照某种策略从就绪队列中选取一个进程,将处理机分配给它。

进程调度是操作系统中最基本的一种调度,在一般的操作系统中都必须配置进程调度。进程调度的频率很高,一般几十毫秒一次。

(3)中级调度

image-20220126121252789

内存不够时,可将某些进程的数据调出外存。等内存空闲或者进程需要运行时再重新调入内存。

暂时调到外存等待的进程状态为挂起状态。被挂起的进程PCB会被组织成挂起队列

中级调度(内存调度)――按照某种策略决定将哪个处于挂起状态的进程重新调入内存。

image-20220126132805729

补充知识:进程的挂起态与七状态模型

image-20220126121943474

3、三级调度的联系

image-20220126122342122


2.2、进程调度的时机、切换与过程

(1)进程调度的时机

image-20220126135810268

(2)进程的切换与过程

image-20220126142901310


2.3、进程调度方式

所谓进程调度方式,是指当某个进程正在处理机上执行时,若有某个更为重要或紧迫的进程需要处理,即有优先权更高的进程进入就绪队列,此时应如何分配处理机。

通常有以下两种进程调度方式:
1)非剥夺调度方式,文称非抢占方式。非剥夺调度方式是指当一个进程正在处理机上执行时,即使有某个更为重要或紧迫的进程进入就绪队列,仍然让正在执行的进程继续执行,直到该进程完成或发生某种事件而进入阻塞态时,才把处理机分配给更为重要或紧迫的进程。

在非剥夺调度方式下,一旦把 CPU分配给一个进程,该进程就会保持CPU直到终止或转换到等待态。这种方式的优点是实现简单、系统开销小,适用于大多数的批处理系统,但它不能用于分时系统和大多数的实时系统。

2)剥夺调度方式,又称抢占方式。剥夺调度方式是指当一个进程正在处理机上执行时,若有某个更为重要或紧迫的进程需要使用处理机,则立即暂停正在执行的进程,将处理机分配给这个更为重要或紧迫的进程。

采用剥夺式的调度,对提高系统吞吐率和响应效率都有明显的好处。但“剥夺”不是一种任意性行为,必须遵循一定的原则,主要有优先权、短进程优先和时间片原则等。


2.4、调度的基本准则

不同的调度算法具有不同的特性,在选择调度算法时,必须考虑算法的特性。为了比较处理机调度算法的性能,人们提出了很多评价准则,下面介绍其中主要的几种:

(1)CPU 利用率

CPU是计算机系统中最重要和昂贵的资源之一,所以应尽可能使CPU保持“忙”状态,使这一资源利用率最高。

利 用 率 = 忙 碌 的 时 间 总 时 间 利用率=\frac{忙碌的时间}{总时间} =

Eg:某计算机只支持单道程序,某个作业刚开始需要在CPU上运行5秒,再用打印机打印输出5秒,之后再执行5秒,为能结束。在此过程中,CPU利用率、打印机利用率分别是多少?
C P U 利 用 率 = 5 + 5 5 + 5 + 5 = 66.66 % CPU利用率=\frac{5+5}{5+5+5}= 66.66\% CPU=5+5+55+5=66.66%
打 印 机 利 用 率 = 5 15 = 33.33 % 打印机利用率=\frac{5}{15} = 33.33\% =155=33.33%

(2)系统吞吐量

表示单位时间内CPU完成作业的数量。

系 统 吞 吐 量 = 总 共 完 成 多 少 道 作 业 总 共 花 费 多 少 时 间 系统吞吐量=\frac{总共完成多少道作业}{总共花费多少时间} =

Eg:某计算机系统处理完10道作业,共花费100秒,则系统吞吐量为?
10/100=0.1道/秒

(3)周转时间

周转时间,是指从作业被提交给系统开始到作业完成为止的这段时间间隔
它包括四个部分:①作业在外存后备队列上等待作业调度(高级调度)的时间、②进程在就绪队列上等待进程调度(低级调度)的时间、③进程在CPU上执行的时间、④进程等待I/O操作完成的时间。后三项在一个作业的整个处理过程中,可能发生多次。

作业的周转时间可用公式表示如下:
** 周 转 时 间 = 作 业 完 成 时 间 – 作 业 提 交 时 间 周转时间=作业完成时间–作业提交时间 =**​

平均周转时间是指多个作业周转时间的平均值:
** 平 均 周 转 时 间 = ( 作 业 1 的 周 转 时 间 + … 十 , 作 业 n 的 周 转 时 间 ) n 平均周转时间=\frac{(作业1的周转时间+…十,作业n的周转时间)}{n} =n(1,n)**​

带权周转时间是指作业周转时间与作业实际运行时间的比值:
带 权 周 转 时 间 = 作 业 周 转 时 间 作 业 实 际 运 行 时 间 = 作 业 完 成 时 间 – 作 业 提 交 时 间 作 业 实 际 运 行 时 间 带权周转时间=\frac{作业周转时间}{作业实际运行时间}=\frac{作业完成时间–作业提交时间}{作业实际运行时间} ==

平均带权周转时间是指多个作业带权周转时间的平均值:
平 均 带 权 周 转 时 间 = ( 作 业 1 的 带 权 周 转 时 间 + . … + 作 业 n 的 带 权 周 转 时 间 ) n 平均带权周转时间=\frac{(作业1的带权周转时间+.…+作业n的带权周转时间)}{n} =n(1+.n)

(4)等待时间

等待时间,指进程/作业处于等待处理机状态时间之和,等待时间越长,用户满意度越低。

image-20220126152232944

对于进程来说,等待时间就是指进程建立后等待被服务的时间之和,在等待I/O完成的期间其实进程也是在被服务的,所以不计入等待时间。
对于作业来说,不仅要考虑建立进程后的等待时间,还要加上作业在外存后备队列中等待的时间
一个作业总共需要被CPU服务多久,被I/O设备服务多久一般是确定不变的,因此调度算法其实只会影响作业/进程的等待时间。当然,与前面指标类似,也有“平均等待时间”来评价整体性能。

(5)响应时间

响应时间指从用户提交请求到系统首次产生响应所用的时间。


2.5、典型的调度算法


1、先来先服务(FCFS)

image-20220126162020253

image-20220126162305425


2、短作业优先(SJF)

image-20220126163456451


非抢占式

image-20220126164409274


抢占式

image-20220126170816125

备注:按①②③方框思路执行。


3、高响应比优先(HRRN)

image-20220126171834470

image-20220126171913985


4、时间片轮转调度算法

image-20220126190919266

QQ浏览器图集_1643196593905


5、优先级调度算法

image-20220126194242480

非抢占式

image-20220126195633540


抢占式

image-20220126201905558


6、多级反馈队列调度算法

image-20220126202631877

image-20220126215350500


思路解析(较复杂)

分析时注意看上面例题的红色字体

QQ浏览器图集_1643205102001



3、进程同步


3.1、进程同步的基本概念


1、临界资源

虽然多个进程可以共享系统中的各种资源,但其中许多资源一次只能为一个进程所用,我们将一次仅允许一个进程使用的资源称为临界资源。许多物理设备都属于临界资源,如打印机等。此外,还有许多变量、数据等都可以被若干进程共享,也属于临界资源。

对临界资源的访问,必须互斥地进行,在每个进程中,访问临界资源的那段代码称为临界区。为了保证临界资源的正确使用,可把临界资源的访问过程分成4个部分:
1)进入区。为了进入临界区使用临界资源,在进入区要检查可否进入临界区,若能进入临界区,则应设置正在访问临界区的标志,以阻止其他进程同时进入临界区。
2)临界区。进程中访问临界资源的那段代码,又称临界段。
3)退出区。将正在访问临界区的标志清除。
4)剩余区。代码中的其余部分。

do {
	entry section;			//进入区
	critical section;		//临界区
	exit section;				//退出区
	remainder section;	//剩余区
] while(true)

2、同步

同步亦称直接制约关系,是指为完成某种任务而建立的两个或多个进程,这些进程因为需要在某些位置上协调它们的工作次序而等待、传递信息所产生的制约关系。进程间的直接制约关系源于它们之间的相互合作。
例如,输入进程A通过单缓冲向进程B提供数据。当该缓冲区空时,进程B不能获得所需数据而阻塞,一旦进程A将数据送入缓冲区,进程B就被唤醒。反之,当缓冲区满时,进程A被阻塞,仅当进程B取走缓冲数据时,才唤醒进程A。

3、互斥

互斥也称间接制约关系。当一个进程进入临界区使用临界资源时,另一个进程必须等待,当占用临界资源的进程退出临界区后,另一进程才允许去访问此临界资源。
例如,在仅有一台打印机的系统中,有两个进程A和进程B,若进程A需要打印时,系统已将打印机分配给进程B,则进程A必须阻塞。一旦进程B将打印机释放,系统便将进程A唤醒,并将其由阻塞态变为就绪态。
为禁止两个进程同时进入临界区,向步机制应遵循以下准则:
1)空闲让进。临界区空闲时,可以允许一个请求进入临界区的进程立即进入临界区。
2)忙则等待。当已有进程进入临界区时,其他试图进入临界区的进程必须等待。
3)有限等待。对请求访问的进程,应保证能在有限时间内进入临界区。
4)让权等待。当进程不能进入临界区时,应立即释放处理器,防止进程忙等待。


3.2、实现临界区互斥的基本方法


1、软件实现方法

(1)单标志法

算法思想:两个进程在访问完临界区后会把使用临界区的权限转交给另一个进程。也就是说每个进程进入临界区的权限只能被另一个进程赋予

image-20220126225128814

(2)双标志先检查

算法思想:设置一个布尔型数组flag[],数组中各个元素用来标记各进程想进入临界区的意愿,比如“flag[0]=ture”意味着0号进程P现在想要进入临界区。每个进程在进入临界区之前先检查当前有没有别的进程想进入临界区,如果没有,则把自身对应的标志flag[i]设为true,之后开始访问临界区。

image-20220127111223866

(3)双标志后检查

算法思想:双标志先检查法的改版。前一个算法的问题是先“检查”后“上锁”,但是这两个操作又无法一气呵成,因此导致了两个进程同时进入临界区的问题。因此,人们又想到先“上锁”后“检查”的方法,来避免上述问题。

image-20220127111622367

(4)Peterson算法

image-20220127113639671


2、总结

image-20220127115203674


2、硬件实现方法

(1)中断屏蔽

利用“开/关中断指令”实现(与原语的实现思想相同,即在某进程开始访问临界区到结束访问为止都不允许被中断,也就不能发生进程切换,因此也不可能发生两个同时访问临界区的情况)

image-20220127131106618

优点:简单、高效
缺点:不适用于多处理机;只适用于操作系统内核进程,不适用于用户进程(因为开/关中断指令只能运行在内核态,这组指令如果能让用户随意使用会很危险)

(2)TestAndSet指令

简称TS指令,也有地方称为TestAndSetLock指令,或TSL指令
TSL指令是用硬件实现的,执行的过程不允许被中断,只能一气呵成。以下是用c语言描述的逻辑。

image-20220127131623003

若刚开始lock是 false,则TSL返回的old值为false,while循环条件不满足,直接跳过循环,进入临界区。
若刚开始lock是 true,则执行TLS后old返回的值为true,while循环条件满足,会一直循环,直到当前访问临界区的进程在退出区进行“解锁”。

相比软件实现方法,TSL指令把“上锁”和“检查”操作用硬件的方式变成了一气呵成的原子操作。
优点:实现简单,无需像软件实现方法那样严格检查是否会有逻辑漏洞;适用于多处理机环境。
缺点:不满足“让权等待”原则,暂时无法进入临界区的进程会占用CPU并循环执行TSL指令,从而导致“忙等”。

(3)Swap指令

有的地方也叫Exchange指令,或简称XCHG指令。
Swap指令是用硬件实现的,执行的过程不允许被中断,只能一气呵成。以下是用c语言描述的逻辑:

image-20220127132935247

逻辑上来看Swap和TSL并无太大区别,都是先记录下此时临界区是否已经被上锁(记录在old变量上),再将上锁标记lock设置为true,最后检查old,如果old为 false则说明之前没有别的进程对临界区上锁,则可跳出循环,进入临界区。

优点:实现简单,无需像软件实现方法那样严格检查是否会有逻辑漏洞;适用于多处理机环境。
缺点:不满足“让权等待”原则,暂时无法进入临界区的进程会占用CPU并循环执行TSL指令,从而导致“忙等”。

image-20220127140652034


3.3、信号量

用户进程可以通过使用操作系统提供的一对原语来对信号量进行操作,从而很方便的实现了进程互斥、进程同步。

信号量其实就是一个变量(可以是一个整数,也可以是更复杂的记录型变量),可以用一个信号量来表示系统中某种资源的数量,比如:系统中只有一台打印机,就可以设置一个初值为1的信号量。

原语是一种特殊的程序段,其执行只能一气呵成,不可被中断。原语是由关中断/开中断指令实现的。软件解决方案的主要问题是由“进入区的各种操作无法一气呵成”,因此如果能把进入区、退出区的操作都用“原语”实现,使这些操作能“一气呵成”就能避免问题。

一对原语: wait(S)原语和 signal(S)原语,可以把原语理解为我们自己写的函数,函数名分别为wait和 signal,括号里的信号量s其实就是函数调用时传入的一个参数。

wait、signal原语常简称为P、v操作(来自荷兰语proberen和verhogen)。因此,做题的时候常把wait(S)、signal(S)两个操作分别写为P(S)、v(S)


1、整型信号量

用一个整数型的变量作为信号量,用来表示系统中某种资源的数量

与普通整数变量的区别:对信号量的操作只有三种,即初始化、P操作、v操作。

image-20220127220417348


2、记录型信号量

整型信号量的缺陷是存在“忙等”问题,因此人们又提出了“记录型信号量”,即用记录型数据结构表示的信号量。

image-20220131143602672

image-20220131144207401


3、利用信号量实现同步

进程同步:要让各并发进程按要求有序地推进。

image-20220131150300372

image-20220131151208846


4、利用信号量实现互斥

image-20220131145417168


5、利用信号量实现前驱关系

image-20220131163607319


6、信号量机制总结

image-20220131164944629


3.4、经典同步问题


1、生产者-消费者问题

**问题描述:**一组生产者进程和一组消费者进程共享一个初始为空、大小为n的缓冲区,只有缓冲区没满时,生产者才能把消息放入缓冲区,否则必须等待了只有缓冲区不空时,消费者才能从中取出消息,否则必须等待。由于缓冲区是临界资源,它只允许一个生产者放入消息,或一个消费者从中取出消息。

image-20220131165824126

问题分析:
1)关系分析。生产者和消费者对缓冲区互斥访问是互斥关系,同时生产者和消费者又是一个相互协作的关系,只有生产者生产之后,消费者才能消费,它们也是同步关系。
2)整理思路。这里比较简单,只有生产者和消费者两个进程,正好是这两个进程存在着互斥关系和同步关系。那么需要解决的是互斥和同步PV操作的位置。
3)信号量设置。信号量 mutex 作为互斥信号量,用于控制互斥访问缓冲池,互斥信号量初值为1;信号量 full用于记录当前缓冲池中的“满”缓冲区数,初值为0;信号量empty用于记录当前缓冲池中的“空”缓冲区数,初值为n。

image-20220131171649169

如何实现

image-20220131193720166

思考:能否改变相邻P、V操作的顺序?

image-20220131193825682


2、多生产者-多消费者问题

**问题描述:**桌子上有一个盘子,每次只能向其中放入一个水果。爸爸专向盘子中放苹果,妈妈专向盘子中放橘子,儿子专等吃盘子中的橘子,女儿专等吃盘子中的苹果。只有盘子为空时,爸爸或妈妈才可向盘子中放一个水果;仅当盘子中有自己需要的水果时,儿子或女儿可以从盘子中取出。

问题分析:
1)关系分析。这里的关系要稍复杂一些。由每次只能向其中放入一只水果可知,爸爸和妈妈是
互斥关系。爸爸和女儿、妈妈和儿子是同步关系,而且这两对进程必须连起来,儿子和女儿之间没有互斥和同步关系,因为他们是选择条件执行,不可能并发,如图2.9所示。image-20220131205516725
2)整理思路。这里有4个进程,实际上可抽象为两个生产者和两个消费者被连接到大小为1
的缓冲区上。
3)信号量设置。首先将信号量plate设置互斥信号量,表示是否允许向盘子放入水果,初值为1表示允许放入,且只允许放入一个;信号量 apple表示盘子中是否有苹果,初值为0表示盘子为空,不许取,apple = 1表示可以取;信号量orange表示盘子中是否有橘子,初值为0 表示盘子为空,不许取,orange =1表示可以取。

如何实现

image-20220131214512450


3、吸烟者问题

问题描述:假设一个系统有三个抽烟者进程一个供应者进程。每个抽烟者不停地卷烟并抽掉它,但是要卷起并抽掉一支烟,抽烟者需要有三种材料:烟草、纸和胶水。三个抽烟者中,第一个拥有烟草、第二个拥有纸、第三个拥有胶水。供应者进程无限地提供三种材料,供应者每次将两种材料放桌子上,拥有剩下那种材料的抽烟者卷一根烟并抽掉它,并给供应者进程一个信号告诉完成了,供应者就会放另外两种材料再桌上,这个过程一直重复(让三个抽烟者轮流地抽烟)

image-20220201162158615

问题分析:
1)关系分析。供应者与三个抽烟者分别是同步关系。由于供应者无法同时满足两个或以上的抽烟者,三个抽烟者对抽烟这个动作互斥(或由三个抽烟者轮流抽烟得知)
2)整理思路。显然这里有4个进程。供应者作为生产者向三个抽烟者提供材料。
3)信号量设置。信号量offer1 , offer2, offer3分别表示烟草和纸组合的资源、烟草和胶水组合的资源、纸和胶水组合的资源。信号量 finish用于互斥进行抽烟动作。

image-20220201194933687


4、读者写者问题

**问题描述:**有读者和写者两组并发进程,共享一个文件,当两个或以上的读进程同时访问共享数据时不会产生副作用,但若某个写进程和其他进程(读进程或写进程)同时访问共享数据时则可能导致数据不一致的错误。因此要求:①允许多个读者可以同时对文件执行读操作;②只允许一个写者往文件中写信息;⑧任一写者在完成写操作之前不允许其他读者或写者工作;④写者执行写操作前,应让已有的读者和写者全部退出。

image-20220201210703259

问题分析:
1))关系分析。由题目分析读者和写者是互斥的,写者和写者也是互斥的,而读者和读者不存在互斥问题。
2)整理思路。两个进程,即读者和写者。写者是比较简单的,它和任何进程互斥,用互斥信号量的Р操作、V操作即可解决。读者的问题比较复杂,它必须在实现与写者互斥的同时,实现与其他读者的同步,因此简单的一对Р操作、V操作是无法解决问题的。这里用到了一个计数器,用它来判断当前是否有读者读文件。当有读者时,写者是无法写文件的,此时读者会一直占用文件,当没有读者时,写者才可以写文件。同时,这里不同读者对计数器的访问也应该是互斥的。
3)信号量设置。首先设置信号量count为计数器,用于记录当前读者的数量,初值为0;设置mutex为互斥信号量,用于保护更新count变量时的互斥;设置互斥信号量rw,用于保证读者和写者的互斥访问。

如何实现

image-20220201210913738


对潜在问题的解决

image-20220201211854332

5、哲学家进餐问题

**问题描述:**一张圆桌边上坐着5名哲学家,每两名哲学家之间的桌上摆一根筷子,桌子的中间是一碗米饭。哲学家们倾注毕生精力用于思考和进餐,哲学家在思考时,并不影响他人。只有当哲学家饥饿时,才试图拿起左、右两根筷子(一根一根地拿起)。若筷子已在他人手上,则需要等待。饥饿的哲学家只有同时拿到了两根筷子才可以开始进餐,进餐完毕后,放下筷子继续思考。

image-20220201213414494

问题分析:
1)关系分析。5名哲学家与左右邻居对其中间筷子的访问是互斥关系。
2)整理思路。显然,这里有5个进程。本题的关键是如何让一名哲学家拿到左右两根筷子而不造成死锁或饥饿现象。解决方法有两个:一是让他们同时拿两根筷子;二是对每名哲学家的动作制定规则,避免饥饿或死锁现象的发生。
3)信号量设置。定义互斥信号量数组chopstick[5]= {1,1,1,1,1},用于对5个筷子的互斥访问。哲学家按顺序编号为0~4,哲学家i左边筷子的编号为i,哲学家右边筷子的编号为(i+1)%5。

image-20220201215820540

如何实现

为防止死锁发生,可对哲学家进程施加一些限制条件,比如
1)至多允许4名哲学家同时进餐;
2)仅当一名哲学家左右两边的筷子都可用时,才允许他抓起筷子;
3)对哲学家顺序编号,要求奇数号哲学家先拿左边的筷子,然后再拿右边的筷子,而偶数号哲学家刚好相反。

制定的正确规则如下:假设采用第二种方法,当一名哲学家左右两边的筷子都可用时,才允许他抓起筷子。image-20220201220136419

3.5、管程


1、为什么要引入管程

image-20220201220445610


2、管程的定义和基本特征

管程是一种特殊的软件模块,有这些部分组成:

1.局部于管程的共享数据结构说明;
2.对该数据结构进行操作的一组过程;
3.对局部于管程的共享数据设置初始值的语句;
4.管程有一个名字。

跨考Tips:“过程”其实就是“函数”

管程的基本特征:

  1. 局部于管程的数据只能被局部于管程的过程所访问;
  2. 一个进程只有通过调用管程内的过程才能进入管程访问共享数据;
    3. 每次仅允许一个进程在管程内执行某个内部过程。

3、扩展1:用管程解决生产者消费问题

image-20220405133454282

每次仅允许一个进程在管程内执行某个内部过程。

例1:两个生产者进程并发执行,依次调用了insert过程…

image-20220405134202092

编译器会暂时阻止第二个进程进入insert函数,将第二个进程阻塞在insert函数外。等第一个进程结束后第二个进程才可以执行insert函数。

例2:两个消费者进程先执行,生产者进程后执行…

image-20220405135246818

总结

引入管程的目的无非就是要更方便地实现进程互斥和同步

  1. 需要在管程中定义共享数据(如生产者消费者问题的缓冲区)
  2. 需要在管程中定义用于访问这些共享数据的“入口”―—其实就是一些函数(如生产者消费者问题中,可以定义一个函数用于将产品放入缓冲区,再定义一个函数用于从缓冲区取出产品)
  3. 只有通过这些特定的“入口”才能访问共享数据
  4. 管程中有很多“入口”,但是每次只能开放其中一个“入口”,并且只能让一个进程或线程进入(如生产者消费者问题中,各进程需要互斥地访问共享缓冲区。管程的这种特性即可保证一个时间段内最多只会有一个进程在访问缓冲区。注意:这种互斥特性是由编译器负责实现的,程序员不用关心)
  5. 可在管程中设置条件变量及等待/唤醒操作以解决同步问题。可以让一个进程或线程在条件变量上等待(此时,该进程应先释放管程的使用权,也就是让出“入口”)﹔可以通过唤醒操作将等待在条件变量上的进程或线程唤醒。

程序员可以用某种特殊的语法定义一个管程(比如: monitor ProducerConsumer …end monitor;),之后其他程序员就可以使用这个管程提供的特定“入口”很方便地使用实现进程同步/互斥了。


4、扩展2:Java中类似管程的机制

image-20220405140628842


5、知识回顾与重要考点

image-20220405140824151


4、死锁


4.1、死锁的概念


1、什么是死锁

image-20220405141743417

在并发环境下,各进程因竞争资源而造成的一种互相等待对方手里的资源,导致各进程都阻塞,都无法向前推进的现象,就是“死锁”。发生死锁后若无外力干涉,这些进程都将无法向前推进。


2、进程死锁、饥饿、死循环的区别

死锁:各进程互相等待对方手里的资源,导致各进程都阻塞,无法向前推进的现象。

饥饿:由于长期得不到想要的资源,某进程无法向前推进的现象。比如:在短进程优先(SPF)算法中,若有源源不断的短进程到来,则长进程将一直得不到处理机,从而发生长进程“饥饿”。

死循环:某进程执行过程中一直跳不出某个循环的现象。有时是因为程序逻辑bug 导致的,有时是程序员故意设计的。

image-20220405143722999


3、死锁产生的必要条件

产生死锁必须同时满足一下四个条件,只要其中任一条件不成立,死锁就不会发生。

互斥条件:只有对必须互斥使用的资源的争抢才会导致死锁(如哲学家的筷子、打印机设备)。像内存、扬声器这样可以同时让多个进程使用的资源是不会导致死锁的(因为进程不用阻塞等待这种资源)。

不剥夺条件:进程所获得的资源在未使用完之前,不能由其他进程强行夺走,只能主动释放。

请求和保持条件:进程已经保持了至少一个资源,但又提出了新的资源请求,而该资源又被其他进程占有,此时请求进程被阻塞,但又对自己已有的资源保持不放。

循环等待条件:存在一种进程资源的循环等待链,链中的每一个进程已获得的资源同时被下一个进程所请求。

注意!发生死锁时一定有循环等待,但是发生循环等待时未必死锁(循环等待是死锁的必要不充分条件)

如果同类资源数大于1,则即使有循环等待,也未必发生死锁。但如果系统中每类资源都只有一个,那循环等待就是死锁的充分必要条件了。


4、什么时候会发生死锁
  1. 对系统资源的竞争。各进程对不可剥夺的资源(如打印机)的竞争可能引起死锁,对可剥夺的资源(CPU)的竞争是不会引起死锁的。
  2. 进程推进顺序非法。请求和释放资源的顺序不当,也同样会导致死锁。例如,并发执行的进程P1、P2分别申请并占有了资源R1、R2,之后进程P1又紧接着申请资源R2,而进程P2又申请资源R1,两者会因为申请的资源被对方占有而阻塞,从而发生死锁。
  3. 信号量的使用不当也会造成死锁。如生产者-消费者问题中,如果实现互斥的P操作在实现同步的P操作之前,就有可能导致死锁。(可以把互斥信号量、同步信号量也看做是一种抽象的系统资源)

总之,对不可剥夺资源的不合理分配,可能导致死锁。


5、死锁的处理策略
  1. 预防死锁。破坏死锁产生的四个必要条件中的一个或几个。
  2. 避免死锁。用某种方法防止系统进入不安全状态,从而避免死锁(银行家算法)
  3. 死锁的检测和解除。允许死锁的发生,不过操作系统会负责检测出死锁的发生,然后采取某种措施解除死锁。

6、知识回顾与重要考点

image-20220405150825722


4.2、死锁预防


1、破坏互斥条件

image-20220405160156630


2、破坏不剥夺条件

image-20220405161212164


3、破坏请求和保持条件

image-20220405162418604


4、破坏循环等待条件

image-20220416194228733


知识回顾

image-20220416194323378

4.3、死锁避免


1、什么是安全序列

image-20220416195944943


image-20220416200151718


image-20220416200339806

image-20220416200612527

image-20220416200803842


2、安全序列、不安全状态、死锁的联系

image-20220416201436538


3、银行家算法

image-20220416202017498


image-20220416202535651

image-20220416202642813

image-20220416203048853

image-20220416203243720

image-20220416203554488

image-20220416204047528


image-20220416204701201

image-20220416204805981


image-20220416205008353

image-20220416205220433


image-20220416211711311

image-20220416211935566

知识回顾

image-20220416212151913

4.4、 死锁检测和解除


1、死锁的检测

image-20220416212929208


image-20220416213344900

image-20220416213809745

image-20220416214255742

image-20220416214343153

如果按上述过程分析,最终能消除所有边,就称这个图是可完全简化的。此时一定没有发生死锁(相当于能找到一个安全序列)


image-20220416214721253

image-20220416214837332

如果最终不能消除所有边,那么此时就是发生了死锁

最终还连着边的那些进程就是处于死锁状态的进程。


image-20220416215559361

image-20220416215635663

死锁定理:如果某时刻系统的资源分配图是不可完全简化的,那么此时系统死锁.


2、死锁的解除

image-20220416220419006


3、知识回顾

image-20220416220647507

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值