概述
本系列文章为西安电子科技大学出版社的《操作系统》所做笔记,可供复习,预习,408使用。
本章节所使用的课件截图来自于网课操作系统
本系列文章也会有配套题目的解析,请点一下关注或者点入本人空间查找,谢谢支持
本文页数对应:P52--------------->P90
本文目的与要求:
2.4 进程同步(重要!!!)
为保证多个进程有条不紊的运行,在多道程序系统中,必须引入进程同步机制
进程同步机制——硬件同步机制,信号量机制
2.4.1 进程同步的基本概念
临界资源(重要!)
临界资源例子:打印机,磁带机
生产着-消费者问题
循环缓冲
Var n, integer;
type item-......
var buffer:array[0,1,...,n-1] of item: // 用数组表示具有n个缓冲区的缓冲池
in, out: 0,1,...,n-1; 初始为1
counter: 0,1,...,n; 初始为0,生产+1,消费-1
// in-生产者, out-消费者
会出现的问题:
问题解决方法:将变量counter作为临界资源处理,亦即,生产者进程和消费者进程互斥的访问变量counter。
临界区
2.4.2 硬件同步机制
实际上,对临界区进行管理时,可以将标志看成一个锁,“锁开”进入,“锁关”等待。
- 关中断
是实现互斥的最简单的方法之一。在进入锁测试之前关闭中断,直到完成锁测试并上锁后才能打开中断。
- 利用Test-and-Set指令实现互斥
boolean TS(boolean *lock)
{
boolean old;
old = *lock;
*lock = TRUE;
return old;
}
这条指令不可分割,即可视为一条原语
*lock为FALSE时即资源空闲,*lock为TRUE时即资源正在被使用
- 利用Swap指令实现进程互斥
方法是为每个临界资源设置一个全局的布尔变量lock,其初值为false,在每个进程中再利用一个局部布尔变量Key。
void swap(boolean *a, boolean *b)
{
boolean temp;
temp = *a;
*a = *b;
*b = temp;
}
上述硬件指令能有效实现进程互斥,但是当临界资源忙碌时,不符合让权等待的规则,很难处理复杂的进程同步问题。
2.4.3 信号量机制(重要!!!!)
整型信号量
V操作:释放资源,退出区的操作
P操作:申请资源, 进入区的操作
由于原子操作是不可中断的,所以出现了盲等
记录型信号量(重要!!!!!)
不存在“忙等”现象
AND型信号量
代码的实现:
信号量集
几种特殊情况:
2.4.4 信号量的应用
-
利用信号量实现进程互斥
-
利用信号量实现前驱关系(会考)
会考的题型:如书P62页
有几个直接后继就有几个公用信号量(a,b,c…)
-
利用记录型信号量实现同步
2.4.5 管制机制 (不考察)
2.5 经典的进程同步问题(重要!!!!)
2.5.1 生产者-消费者问题
1. 用记录型信号量解决
具体实现:
这里wait(empty) 在wait(mutex)之前执行,不能颠倒,因为wait(mutex)是代表生产者是否能使用缓冲区是互斥的,如果先使用缓冲区会导致死锁
注意:!!!
2. 用AND信号量解决
2.5.2 哲学家进餐问题
1. 用记录型信号量解决
问题:当五个哲学家同时饿了,会同时拿起左边的筷子,无法进入临界区,会死锁
解决方法:
定义一个资源信号量count初值为4,即最多只允许有四位哲学家同时去拿左边的筷子
哲学家按奇偶数顺序拿筷子
2. 用AND信号量解决
2.5.3 读者-写者问题
1. 用记录型信号量解决
由于记录型信号量机制存在对写者不公平的现象,所以用信号量集的机制去解决该问题
2. 用信号量集机制解决
2.6 进程通信(高级通信)
高级通信命令(原语)
2.6.1 进程通信的类型
(1)共享存储器系统
数据的形式和位置和访问控制都是由进程负责,而不是OS
(2)管道通信系统
(3)消息传递系统
(4)客户机-服务器系统
当前主流的通信实现机制
其主要实现方法分为三类:套接字,远程过程调用,远程方法调用
(1)套接字(Socket)
解决:多对进程同时通信时端口和物理线路的多路复用问题
每个套接字都拥有唯一的套接字号(套接字标识符)
一个套接字是一个通信标识类型的数据结构,包含了通信目的的地址,通信使用的端口号,通信网络的传输层协议,进程所在的网络地址,以及针对客户或服务器程序提供的不同系统调用(或API函数)等,是进程通信和网络通信的基本构件。
套接字一般包含两类:
- 基于文件型
- 基于网络型:采用非对称方式通信,即发送者需要提供接收者命名。
(2)远程过程调用,远程方法调用
远程过程函数调用RPC,是一个通信协议,用于通过网络连接的系统。如果涉及的软件采用面向对象编程,即远程过程调用亦称为远程方法调用
2.6.2 消息传递通信的实现方法
(1) 直接通信方式
message相当于临时变量
对称寻址与非对称寻址:
对称寻址的不足在于,一旦改变进程的名称,则可能需要检查所有其他进程的定义,不利于进程定义的模块化
非对称寻址:
某些情况下,接收进程可能需要与多个发送进程通信,无法事先指定发送进程。(例如打印机,可以接受来自任何一个进程的打印请求)对于这种情况,在接受进程的原语中不需要命名发送进程,只填写表示源进程的参数,即完成通信后的返回值,而发送进程还是需要命名接收进程。
send(P, message); 发送一个消息给进程P
rececive(id, message); 接受来自任何进程的消息,id变量设置成进行通信的发送方进程id或名字
(2) 信箱通信
用户:私用信箱(单向通信链路)
操作系统:公用信箱(双向通信链路)
进程:共享信箱
信箱定义为一种数据结构:信箱头+信箱体
信箱通信原语:
send(mailbox, message); 发送一个消息到指定邮箱
rececive(mailbox, message); 从指定邮箱接受一条消息
2.6.3 消息传递系统实现的若干问题
2.6.4 直接消息传递系统实例
不考,了解即可
2.7 线程的基本概念
引入线程目的:为了减少程序在并发执行时所付出的时空开销,使OS有更好的并发性
2.7.1 线程的引入
2.7.2 线程与进程的比较
2.7.3 线程的状态和线程控制块