【操作系统⑥】——进程联系与临界区管理【同步与互斥 Dekker算法 TS指令 SWAP指令】

本文深入探讨了操作系统中进程的联系,包括顺序与并发环境的区别、进程的不确定性、相交与无关进程的概念,重点解析了进程同步与互斥的基本原理和管理方法。通过实例分析了临界区的概念,介绍了Dekker算法和硬件方法如TS指令、交换指令在解决进程互斥中的应用,并讨论了各种方法的优缺点。
摘要由CSDN通过智能技术生成

🔐



Welcome ☁️
上一篇文章地址链接: 【操作系统⑤】——处理器的调度【调度算法 FCFS、SJF、SRTF、HRN】.
下一篇文章地址链接: 【操作系统⑦】——信号量与PV操作(上)【生产者消费者经典问题】.

期末考试总复习——地址链接《操作系统期末总复习——绝地求生版》.


一、进程联系


1、顺序程序与顺序环境

  ● 顺序环境
    ① 程序的指令或语句序列是顺序的。
    ② 在计算机系统中只有一个程序在运行。
    ③ 一个程序独占系统中的所有资源。
    ④ 一个程序执行不受外界影响。

  ● 顺序特征
    ① 顺序性执行
    ② 封闭独占资源
    ③ 确定可再现性(即对于一个程序而言,只要输入相同,则输出也相同)


2、并发环境与并发进程

  ● 并发环境
    ① 在一定时间内,物理机器上有两个或两个以上的程序。
    ② 程序处于开始运行但尚未结束的状态。
    ③ 程序执行次序无法事先确定的。

  ● 并发特征
    ① 程序结果的不可再现性(即对于一个程序而言,尽管输入相同,但输出也不一定相同)
    ② 程序的执行呈现间断性(即:程序在执行过程中可能会被 “打断”)
    ③ 系统中各类资源共享
    ④ 独立性和制约性
    ⑤ 程序和计算不再对应(即程序和进程不再一一对应)


3、与时间有关的不确定性

  ● 在并发环境与并发进程的前提下,系统将产生与时间有关的不确定性。举个栗子具体来理解:

  ◆ 样例:P1 和 P2 是两个并发进程, 变量 C 是一个共享变量。假如一开始,C 的值为 2。然后执行一下 6 条语句:
    ① P1:tmp_1 = C;
    ② P1:tmp_1 = tmp_1 + 1;
    ③ P1:C = tmp_1 ;
    ④ P2:tmp_2 = C;
    ⑤ P2:tmp_2 = tmp_2 + 1;
    ⑥ P2:C = tmp_2;
  那么,当整个程序执行完后,C 的值会等于多少?

  ◆ 很显然,先执行 P1,然后再执行 P2,那么答案是 4 。但是答案不是唯一的,可能是 3 。比如说,P1 先执行,且当 P1 执行完②时(此时C = 3),这时 CPU 调度给了 P2,而当 P2 执行完后 CPU 再调度给 P1,那么最后相当于 C 被赋了两次值,都为 3.


4、相交进程与无关进程

  ● 直接式与间接式的制约关系:
    ① 直接作用(也就是直接式制约):一般发生在两个具有合作关系的进程之间。(也就是说两个进程之间有 “通信的行为”,需要实时地“沟通交流”,以完成“最终任务”)
    ② 间接作用(也就是间接式制约):两个没有合作关系的进程竞争资源。(比如说两个进程之间没有关系,但是它俩都共生在一个系统中,那么它俩就可能就对内存或者其他的 I/O 设备等有一种竞争)

  ● 相交与无关进程:
    ① 相交进程:指在逻辑上存在某种联系的并发进程。
    ② 无关进程:值在逻辑上无任何种联系的并发进程。
  ◆ 注:直接作用发生在相交进程之间。而间接作用可以发生在相交进程或无关进程之间。


5、进程同步与互斥

  ● 进程的同步(实际上就是一种直接作用):即两个或两个以上并发执行的进程需要按照一定的时序关系来合作完成一项任务。
    ① 并发进程彼此相互发送消息进行合作,但因为有直接式制约而需要相互等待,使得各进程按照一定的速度执行,最终完成任务。
    ② 进程间的相互联系是有意识的安排 (是当初设计这个进程的程序员安排的),且直接作用发生在相交进程之间。

  ◆ 样例一:进程的同步(直接作用)

	假设在一个区县客车上,有两个进程:司机进程P1、售票员进程P2
	
	司机 P1 的程序:
	while(true)
	{
		启动车辆();
		正常开车();
		到站停车();
	}
	
	售票员 P2 的程序:
	while(true)
	{
		关门();
		售票();
		开门();
	}

  显然,司机和售票员之间就存在直接的制约关系。司机只有在 售票员把门关好的情况下 才能启动车辆。在 司机正常开车 的过程中,售票员可以进行售票。然后也只有在 司机把到站停好车过后,售票员才能开门。他们的行为就受到彼此之间的制约。

  但是在现实生活中,门是自动门…



  ● 进程的互斥(实际上就是一种间接作用):即各个进程竞争使用资源时发生的一种关系。(在资源里面有一种典型的资源,叫做临界资源)
    ① 临界资源:一次只允许一个进程使用的系统资源。
    ② 进程间通过中介 (即这些临界资源) 发生了联系,这是无意识的安排。
    ③ 可以发生在相交进程之间,也可以发生在无关进程之间。


  ◆ 样例二:进程的互斥(间接作用)
    若干不相识的同学,在期末考试周,去图书馆学习。那些座位就是 “临界资源”。每一个同学就是 “进程”。(一个座位只允许一个同学坐,所以它是临界资源)

  ● 进程同步和互斥的关系
    ① 互斥反映了进程间的竞争关系,而同步则反映了进程间的合作关系。
    ② 进程互斥是进程同步的一种特殊情况,因为互斥所涉及的进程之间没有固定的必然的联系,它们只是竞争获得共享资源的使用权;而同步所涉及的并发进程之间有一钟必然的联系,即使资源可用,若没有获得同步消息,进程也不能去使用。



二、进程联系的思维导图

在这里插入图片描述



三、临界区管理


1、临界区及其使用原则

  ● 临界区:进程中涉及临界资源的程序段。另外,多个进程的临界区称为相关临界区。
    ① 进程中涉及临界资源的程序段
    ② 进程间通过中介 (即这些临界资源) 发生了联系,这是无意识的安排。

  ● 使用原则:
    ① 有空让进(临界区没进程时,允许进程进入)
    ② 无空等待(临界区有进程时,其他进程不能进来,需要等待)
    ③ 多中择一(多个进程想进入临界区时,临界区只会根据某一种规则选择一个进程进入)
    ④ 有限等待(指的是它不会让 想进入临界区的进程 无限等待)


2、临界区管理——软件方法

  ● 软件方法,即通过代码来管理。

  ◆ 样例一(失败的管理方法)

	/* 基于 C 语言语法 */
	bool flag_1 = false;	// 布尔类型,true 代表这个进程想进临界区,false 代表这个进程不想进临界区
	bool flag_2 = false;
	while(true)				// 开始并发执行 P1 和 P2 两个进程;
	{
		进程 P1:
		while( flag_2 == true ) ;	// 如果 P2 想进临界区, 那 P1 就等 P2 搞完
		flag_1 = true;				// 如果 P2 想进临界区, 那 P1 就等 P2 搞完
		P1 进入临界区并做相关操作;
		flag_1 = false;
		
		进程 P2:
		while( flag_1 == true ) ;
		flag_2 = true;
		P2 进入临界区并做相关操作;
		flag_2 = false;
	}						// 结束并发进程;

  ◆ 说明一:(理想情况下)
    ① 一开始 flag_1 和 flag_2 都赋初值为 false。
    ② 若先开始执行进程 P1,那么它会直接跳出 “while( flag_2 == True ) ;” 循环语句。然后将 flag_1 赋值为 true。然后进入临界区。
    ③ 这时在进程 P2 中,发现 flag_1 值为 true,那么 P2 就会一直在 “while( flag_1 == true ) ;” 语句中循环执行。
    ④ 只有当 P1 执行完后,将 flag_1 重新赋值为 false 后,P2 才能跳出循环,然后进入临界区。
    ⑤ 依次类推,依次套娃…

  ◆ 说明二:(不理想情况下)
    ① 一开始 flag_1 和 flag_2 都赋初值为 false。
    ② 若先开始执行进程 P1,那么它会直接跳出 while 循环。然后,就在这个时候,假如 P1 被中断,接着 P2 执行
    ③ 因为 P1 还未来得及将 flag_1 赋值为 true,所以 P2 也会跳出 while 循环。
    ④ 后面就会导致 P1 和 P2 同时进入临界区,这就不符合 临界区第②和③条使用原则。

● 因为可能会出现 “两者同时进入” 的情况,所以说这是一种失败的软件管理。



  ◆ 样例二(失败的管理方法)

	/* 基于 C 语言语法写的伪代码 */
	bool flag_1 = false;	// 布尔类型,true 代表这个进程想进临界区,false 代表这个进程不想进临界区
	bool flag_2 = false;
	while(true)				// 开始并发执行 P1 和 P2 两个进程;
	{
		进程 P1:
		flag_1 = true;				// 不同点
		while( flag_2 == true ) ;	
		P1 进入临界区并做相关操作;
		flag_1 = false;
		
		进程 P2:
		flag_2 = true;				// 不同点
		while( flag_1 == true ) ;
		P2 进入临界区并做相关操作;
		flag_2 = false;
	}						// 结束并发进程;

  ◆ 说明一:(理想情况下)
    ① 一开始 flag_1 和 flag_2 都赋初值为 false。
    ② 若先开始执行进程 P1,它将先把 flag_1 赋值为 true,然后跳出 while循环,再进入临界区。
    ③ 这时在进程 P2 中,发现 flag_1 值为 true,那么 P2 就会一直在 while 循环语句中循环执行。
    ④ 只有当 P1 执行完后,将 flag_1 重新赋值为 false 后,P2 才能跳出循环,然后进入临界区。
    ⑤ 依次类推…

  ◆ 说明二:(不理想情况下)
    ① 一开始 flag_1 和 flag_2 都赋初值为 false。
    ② 若先开始执行进程 P1,将先把 flag_1 赋值为 true,然后,就在这个时候,假如 P1 被中断,接着 P2 执行
    ③ P2 这时也会将 lag_1 赋值为 true。
    ④ 后面就会导致 P1 和 P2 同时都不能进入临界区,这就不符合 临界区第①和④条使用原则。

● 因为可能会出现 “两者一直进不去” 的情况,所以说这也是一种失败的软件管理。



  ◆ 样例三(成功的管理方法)—— Dekker算法:【结合了前两个样例的失败教训】

	/* 基于 C 语言语法写的伪代码 */
	bool flag_1 = false;				// 布尔类型,true 代表这个进程想进临界区,false 代表这个进程不想进临界区
	bool flag_2 = false;
	int turn = 1;						// turn 的值为 1 时代表 P1 该进临界区,值为 2 时代表 P2 该进临界区(我们初值假设为 1)
	while(true)		// 开始并发执行 P1 和 P2 两个进程;
	{
		进程 P1:
		flag_1 = true;					// P1 想进临界区
		while( flag_2 == True )			// P2 也想进临界区
		{
			if( turn == 2 )				// 而且 P2 也该进临界区(注:一开始 turn 初值为 1) 
			{
				flag_1 = false;			// 那么, P1 就说:“既然 P2 想进临界区而且该进,那我先不想了”
				while( turn == 2 ) ;	// 然后 P1 一直等 P2 搞完
				flag_1 = true;			// P1 等 P2 搞完后再 “想进临界区”
			}
		}
		P1 进入临界区并做相关操作;
		turn = 2;						// P1 执行完了,就把 “turn(轮次)” 交给 P2
		flag_1 = false;					// 并且 P1 搞完后也就 “不想进临界区”
		
		进程 P2:
		flag_2 = true;					// P2 想进临界区
		while( flag_1 == True )			// P1 也想进临界区
		{
			if( turn == 1 )				// 而且 P1 也该进临界区
			{
				flag_2 = false;			// P2 说:“既然 P1 想进临界区而且该进,那我先不想了”
				while( turn == 1 ) ;	// 然后 P2 一直等 P1 搞完
				flag_2 = true;			// P2 等 P1 搞完后再 “想进临界区”
			}
		}
		P2 进入临界区并做相关操作;
		turn = 1;						// P2 执行完了,就把 “turn(轮次)” 交给 P1
		flag_2 = false;					// 并且 P2 搞完后也就 “不想进临界区”
	}		// 结束并发进程;

  ● 可以进行检验,无论在哪里中断 P1 和 P2,都不会出现 样例一中“两者同时进入” 和 样例二中“两者一直进不去” 的情况。所以说这是一种成功的软件管理。但是,Dekker 算法算法复杂度较高,开销也比较大。


3、临界区管理——硬件方法

  ● 所谓用硬件的方法,就是说硬件的指令的方法来控制对临界区代码的执行。

  ● TS指令(Test Set):

	/* 基于 C 语言语法写的伪代码 */
	
	bool TS函数( int 进程编号i )
	{
		if( status == true )
		{
			status = false;
			return true;
		}
		else if( status == false )
		{
			return false;
		}
	}
	
	/*  主函数: */
	bool status = true;		// 初始化
	while(true)				// 开始并发执行进程 Pi , i = 1,2,3,...
	{
		对于进程Pi 			
		do
		{
			flag = TS(i);
		}while(flag == true);
		Pi 进入临界区并做相关操作;
		status = true;
	}						// 结束并发进程;

  ◆ 说明:可以发现,如果 P1 进入了临界区,那此时变量 status 为 false,而 flag 为 true。显然,当进程 P2 进来 “掺和” 时,它将会一直在这个 do while 中循环,直到 P1 离开临界区并将 status 重新赋值为 true 时,P2 才能跳出那个循环。同样的,对于 P3、P4、…也是这样。



  ● 交换指令SWAP:可以将两个字的内容进行交换。
  另外,我们为达到目的,还需要设置一个公共变量 lock ,用它来表示临界区是否 “上锁 ”。而且每个进程还有一个私有的变量 key,它可用于与 lock 进行数值交换。

	/* 基于 C 语言语法写的伪代码 */
	
	void SWAP( int *a, int *b )		// 指针传递
	{
		int temp;
		temp = *a;
		*a = *b;
		*b = temp;
	}
	
	/*  主函数: */
	bool 所有Pi的key = true;
	bool lock = false;
	while(true)			// 开始并发执行进程 Pi , i = 1,2,3,...
	{
		对于进程Pi 			
		do
		{
			SWAP(&lock, pi的key);
		}while(Pi的key);
		Pi进入临界区并做相关操作;
		lock = false;
	}					// 结束并发进程;

  ◆ 说明:如果 P1 进入了临界区,那此时变量 lock 为 false,而 P1的key 为 true。显然,当执行 SWAP 后,🔒 和 🔑 的数值一交换后,P1 就能跳出了 do while 循环,然后进入临界区。而这时如果有其他进程进来,因为这时 🔒 为 true,他们将会一直在这个 do while 中循环,直到 P1 离开临界区并将 lock 重新赋值为 false 时,其他进程才能跳出那个循环。



  ● 开关中断指令方法:
    ① 当某个进程进入临界区时,执行 “关中断” 指令。(即不运行其他进程中断 “我” 这个进程的执行)
    ② 当该进程离开临界区后,执行 “开中断” 指令。(即这时其他进程可以中断 “我” )
    ③ 这样就能控制进程互斥地进入临界区。

4、软硬件方法的优缺点

    ① 软硬件方法(除 “开关中断指令” 方法外)都采用了 “忙等待” 的方式。(即未执行的等待进程都是在 while 循环中空转)
    ② 软件方法实现起来比较复杂,需要一定编程的技巧。
    ③ 硬件指令方法的代码简洁有效。
    ④ 硬件中断屏蔽的方法的代价较高。(“关中断”后,就相当于把一个 “并发的环境” 变成了一个 “顺序的环境”。就像在操场上,只有一个出口,刚军训完,全部连队都先去 “争抢” 出口,但是这时教官大喊一声 “关中断”,所有的围着出口的学生不得不重新排队,虽然也是一个连队接着一个连队地出去,但是有些学生可能要走很远,才能达到他重新排队后的位置,所以 “代价” 高)



四、临界区管理的思维导图

在这里插入图片描述



五、参考附录:

[1] 《王道计算机考研 操作系统》
看视频可能快一些,但深刻理解还是需要文字和沉淀
链接: https://www.bilibili.com/video/BV1YE411D7nH?p=2.

[2] 《操作系统A》
我们上课用的慕课
链接: https://www.icourse163.org/course/NJUPT-1003219004?from=searchPage.

[3] 《操作系统教程》
我们上课用的教材

上一篇文章地址链接: 【操作系统⑤】——处理器的调度【调度算法 FCFS、SJF、SRTF、HRN】.

下一篇文章地址链接: 【操作系统⑦】——信号量与PV操作(上)【生产者消费者经典问题】.

期末考试总复习——地址链接《操作系统期末总复习——绝地求生版》.


未完待续…🔐 🔐

  • 6
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

一支王同学

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值