本篇记一些补充或者总结的东西。
2.1 前趋图和程序执行
1.前趋图关注的是前趋关系,不能有循环。
2.多道并发应是“有控制的并发”。
多道程序运行符合前趋图的关系才是合理并发。
没有任何干预下会出现结果不可再现的并发,即错误的并发。
2.2 进程的描述
1.进程的特征
①结构性特征,进程的根本——PCB
②动态性,进程最基本的特征
③并发性
④独立性
⑤异步性
2.区别进程和程序
①动与静
进程是动态的,程序是静态的;程序是有序代码的集合,进程是程序的执行。
②永久与暂时
进程是暂时的,程序是永久的;进程是一个状态变化的过程,程序是可长久保存的。
③结构
进程的组成包括程序、数据和进程控制块(进程各种控制信息)。
④进程与程序的对应关系
都可以一对n。通过多次执行,一个程序可对应多个进程;通过调用关系,一个进程可包括多个程序。
3.创建状态
①申请一个空白PCB
②分配资源
③PCB的初始化工作
④将新进程插入就绪队列
4.进程控制块是进程存在的唯一标志。
5.OS对进程进行控制和管理围绕PCB进行。
6.存放进程的管理和控制信息的数据结构为进程控制块。
2.3 进程控制
1.原语:是由若干指令构成的原子操作过程,作为整体实现功能,不可被打断(CPU关中断)。
2.进程只能挂起自己或其子孙进程。
3.关于调度
①进程控制中,状态转换和调度密切相关。
②运行态进程的改变必然产生调度行为。
③只要产生新就绪态进程,就需考虑调度策略。
只要是采用抢占式调度,要检查新就绪进程是否可抢占CPU,引起新的调度。
4.两种形式的制约关系
①间接相互制约关系:由于共享系统资源(互斥)
②直接相互制约关系:源于进程合作(有序)
5.临界资源:一次仅允许一个进程使用的资源
6.同步机制应遵循的规则:
①空闲让进:资源使用最基本原则
②忙则等待:保证互斥
③有限等待:合适时被唤起防止死等
④让权等待:能主动释放CPU防止忙等
2.4 进程同步
1.进程同步的关键:不应被打断(原语,OS核心态运行)
主要涉及“判断”和“修改标志”操作
2.信号量是一种类型,用户不能修改,但可以自定义调用。
3.整型信号量
①信号量定义为一个整型量
②根据初始情况赋相应的值
③仅能通过两个原子操作来访问:wait(),signal()
4.整型信号量
p操作 wait(s)
{ while(s<=0) do no-op;
s=s-1; }
v操作 signal(s)
{ s:=s+1; }
(s:=s+1)操作只能存在于原语内部,在外部存在是错误的,在外部只能通过系统封装的赋值函数调用。
整型信号量符合“有限等待”原则,不符合“让权等待”原则,所以信号量结构信息发生变化,产生了记录型信号量。
5.记录型信号量
记录型数据结构:整型变量value(代表资源数目)、进程链表L(链接所有等待进程)
代码:
type Semaphore = record
value : integer;
L : list of PCB;
end;
操作:S.value,S.L
value>0表示当前可用资源的数量;
value<=0,其绝对值表示等待使用该资源的进程数,即在该信号量队列上排队的PCB的个数。
6.wait()操作和signal()操作
p操作:wait():
S.value = S.value - 1;
if(S.value < 0) then block(S.L);
v操作:signal():
S.value = S.value + 1;
if(S.value <= 0) then wakeup(S.L);
if仅执行一次,再返回现场时,执行if下一条语句。
7.互斥信号量注意点:
①互斥信号量mutex初值为1;
②每个进程中将临界区代码置于P(mutex)和V(mutex)原语之间;
③必须成对使用P和V原语(在同一进程中),不能次序错误、重复或遗漏。
8.控制同步顺序的注意点
①信号量值为0的点是限制的关键所在;
②成对使用P和V原语(在有先后关系的两个进程中),不能次序错误、重复或遗漏,否则同步顺序出错。
9.示例一
问题描述:设有一供者和一用者,如何用信号量来控制二者对缓冲区的同步使用。
分析:需要两个信号量,s1表示空缓冲的个数,初值为1;s2表示产品的个数,初值为0。
伪代码:
①供者:
……
P(s1);
将数据送入缓冲区;
V(s2);
……
②用者:
……
P(s2);
从缓冲区取数来用;
V(s1);
……
10.示例二
问题描述:有一个果盘,果盘里只能放一个水果,爸爸放梨,妈妈放苹果,儿子吃梨。女儿吃苹果,如何用信号量来控制
分析:需要三个信号量,l表示梨的数量,a表示苹果的数量,e表示空的数量
伪代码:
father()
{ while(True)
{ wait(e);
放梨;
signal(l);
} }
mother()
{ while(True)
{ wait(e);
放苹果;
signal(a);
} }
daugher()
{ while(True)
{ wait(a);
取苹果;
signal(e);
} }
son()
{ while(True)
{ wait(l);
取梨;
signal(e);
} }
main()
{ semaphore l = 0,a = 0,e = 0;
father();
mother();
daughter();
son();
}