操作系统学习-练习题个人总结(五)

操作系统学习-练习题个人总结(五)

第三章 进程管理

一、第四节-进程同步-课堂测试

1、错题解析

  1. 在多进程的系统中,为了保证公共变量的完整性,各进程应互斥进入临界区,所谓临界区是指(一段程序)。

    解析:临界资源:一次仅允许一个进程使用的资源称为临界资源;临界区:进程中访问临界资源的一段代码。

  2. 下面关于管程的说法,不正确的是(管程是一种系统调用)。

    解析:管程比信号量更容易保证并行编程的正确性;管程是一种编程语言成分;管程是一种进程同步机制

  3. 关于管程与进程比较的论述中,正确的是(管程内定义的数据结构能够由多个进程间接访问,进程内定义的是私有数据结构)。

    解析:管程作为操作系统或编程语言成分,与进程一样也具有生命周期,由创建而产生,由撤销而消亡(是语法范围,不能撤销创建,并没有生命周期);管程能被系统中所有的进程调用(管程能被欲使用共享资源的进程调用);管程和调用它的进程能够并行工作(并不,是顺序的)。

2、正确知识点总结

  1. 要实现两个进程互斥,设一个互斥信号量mutex,当mutex为0时,表示(有一个进程进入临界区)。
  2. 有一个信号量的初值为3,经过多次P、V操作后,当前值为-1,则表示等待进入临界区的进程数为(1)。//绝对值的数目就是等待数目
  3. 在使用信号量机制实现互斥时,互斥信号量的初值一般为(1)【表示临界资源数目】;而使用信号量机制实现同步时,同步信号量的初值一般为(0)。
  4. 设与某资源相关联的信号量初值为3,当前值为1,若M表示该资源的可用个数,N表示等待该资源的进程数,则M、N分别为(1;0)
  5. 利用禁止中断的方法来实现互斥,只能用于单处理器系统中。(√)
  6. 不存在忙等现象的机制是(利用记录型信号量实现进程间互斥)。

补充:

进程同步:并发进程在一些关键点上可能需要互相等待或互通消息,这种相互制约的等待或互通消息称为进程同步。

同步机制应遵循的原则:
空闲让进:其他进程均不处于临界区;
忙则等待:已有进程处于其临界区;
有限等待:等待进入临界区的进程不能"死等";
让权等待:不能进入临界区的进程,应释放CPU(如转换到阻塞状态)

进程同步机制:

  • 利用硬件方法解决进程互斥问题(系统自带)
    禁止中断:【缺点】可能增加系统风险;只能用于单处理机系统(一个进程只能禁止本CPU的中断)
    TSL指令:检测并上锁指令;lock=false,通过TSL判断lock变量的值,False-空闲/True-忙碌;会忙等
    Swap指令:交换两个字的内容;lock=false,key=true,使用swap交换两个变量的值,直到key判false;违背让权等待原则(占着CPU等待);会忙等

  • 利用软件方法解决进程互斥问题(代码实现)
    不正确的算法
    (1)设立一个公用整型变量turn,描述允许进入临界区的进程标识,假设初始化turn=0,表示首先轮到P0访问临界资源。【违背了空闲让进(P0使用完成后P1才可使用临界区,若要先让P1进程使用临界区,进程都会空循环)、让权等待原则(在P1使用临界区的时候P0空循环判断,占用CPU并不处于阻塞状态)】
    (2)设立一个标志数组flag[2]:描述进程是否已在临界区,初值均为0(FALSE),表示进程都不在临界区。【违背了忙则等待(同时执行时flag值容易都置为1,即都使用临界区)、让权等待原则(空循环)】
    (3)设立一个标志数组flag[2]:描述进程是否希望进入临界区,初值均为0(FALSE),表示进程都不希望进入临界区。【违背了空闲让进、有限等待、让权等待原则】
    ------有关于这类代码判断违背了哪些原则的题,使用时间片轮转,代码逐条执行

    Peterson算法:结合上述(1)(2)算法,在(2)的基础上引入turn互相谦让,可推广到N个进程之间的互斥操作。【违背让权等待原则,会空循环忙等】

    面包店算法
    每个进程设置一个唯一的编号Pi(i=0…n-1);
    boolean choosing[n]:表示进程是否正在取号,初值为False;
    int number[n]:记录每个进程取到的号码,初值为0。

  • 利用锁机制解决进程互斥问题:w=1忙碌;w=0空闲;使用了加锁lock,开锁unlock原语;(代码思路和“禁止中断”类似,但是更有保障,具体实现也是不一样的)

  • 利用信号量机制解决进程同步与互斥问题
    整型信号量:【重点在于临界资源的占有与释放】
    初始化操作:非负整数–表示临界资源的使用数目;P原语操作:down()或wait()–申请临界资源的操作;V原语操作:up() 或signal()–释放临界资源的使用权【违背了让权等待原则】

wait( S)
{ while(S ≤ 0);//空循环
  S--;
}
signal(S)  { S++ ; }

记录型信号量:【简单说就是记录阻塞的进程,并利用value的值来控制睡眠与唤醒的动作】
value: 初始化为一个非负整数值,表示空闲资源总数--若为非负值表示当前的空闲资源数,若为负值其绝对值表示当前等待临界资源的进程个数(没有申请到而被阻塞),若为0表示无进程也无空闲资源。
L:初值为空

typedef struct{
	int value;/*信号量的值*/
	PCB * L;  /*进程等待队列队首指针*/
}semaphore ;  
semaphore *S;
wait(S)
{ S->value--;
  if(S->value < 0)
	then sleep(S->L);//去阻塞队列,睡眠等待
}
signal(S)
{ S->value++;
  if(S->value ≤ 0)
  	then wakeup(S->L);//唤醒进程
}

信号量集机制:【只要有一类不能分配就都不分配】
一次可申请多类资源;每类资源可申请多个。
s1:进程要互斥共享的多类临界资源;t1:系统规定的分配下限值;d1:一个进程对各类资源的申请数量

Swait(S1,t1,d1,S2,t2,d2, ...,Sn,tn,dn) {
	if (S1>=t1 && ...  && Sn>=tn)
	{	
		for (i=1;i<=n;i++)
		{	
			Si=Si –di;
		}
	}else {
		将当前进程阻塞到第一个Si<ti的信号量Si的阻塞队列中;
		  }
}
Ssignal( S1,d1,S2,d2, ...,Sn,dn)
{
	for (i=1;i<=n;i++)
	{
		Si=Si + di;
		唤醒所有因S1~Sn而阻塞的进程,插入就绪队列;
	}
}

Swait(S,d,d):表示每次申请d个资源
Swait(S,1,1):表示记录型信号量
Swait(S,1,0):可作为一个可控开关
Swait(S1, 1,1,S2,1,1, …,Sn,1,1):表示AND型信号量
PS:一些经典信号量机制解决同步互斥问题的算法,详见本节最后小结。

管程
//定义:一个管程定义了一个数据结构和能为并发进程所执行(在该数据结构上)的一组操作,这组操作能同步进程和改变管程中的数据。
组成:管程名字;局部于管程的共享变量的说明;对该数据结构进行操作的一组过程;初始化局部变量的语句。
特性:信息隐蔽性(外访内;内访内);任一时刻,管程中只能有一个活跃进程。

二、第四节-进程同步-课后作业

  1. 假设有三个并发进程A,B,C,其中A负责从输入设备上读入信息并传送给B,B将信息加工后传送给C,C负责将信息打印输出。进程A、B共享一个单缓冲区,进程B、C共享另一个单缓冲区。(一个单缓冲区中只能放一条信息)。请用记录型信号量实现三个进程间的同步算法。
empty1,empty2,ful1,full2:semaphore
main() {
  empty1,empty2=11;
  full1,full2=0,0;
  parbegin(A,B,C);
}
void A () {
  do{ get data;
      wait(empty1);
      put data to buffer1;
      signal(full1);
  }while(1)
}
void B () {
  do{ wait(full1);
      get data from buffer1;
      signal(empty1);
      wait(empty2);
      put data to buffer2;
      signal(full2);
  }while(1)
}
void C () {
  do{ wait(full2);
      get data from buffer2;
      signal(empty2);
  }while(1)
}
  1. 桌子上有一个空盘子,最多允许存放两只水果,但一次只能一个人操作盘子(往盘子中放水果或从盘子中取水果),爸爸可以向盘中放苹果,妈妈向盘子中放橘子,女儿专门吃盘子中的苹果,儿子专门吃盘子中的橘子。请用信号量实现他们之间的同步与互斥关系。
S:semaphore=2;//盘子开始可以放两只水果
Mutex:semaphore=1;//互斥使用盘子
S1:semaphore=0;//是否有苹果
S2 :semaphore=0;//是否有橘子
Process  Father:
Begin: L1: P(S);
       P(mutex);
       Put Apple;
       V(mutex);
       V(S1);     
       GO TO L1;
End;
Process Son: 
Begin: L3: P(S2);
       P(mutex);
       Get  Orange;
       V(mutex);
       V(S);
       GO TO L1;
End;
Process Mother:
Begin:L2: P(S);
      P(mutex);
      Put Orange;
      V(S2);
      V(mutex);
      GO TO L2;
End;
Process Daughter:
Begin:L4: P(S1);
      P(mutex)
      Get Apple;
      V(mutex);
      V(S);
     GO TO L4;
End;
  1. 某工厂有一个可以存放设备的仓库,总共可以存放10台设备。生产的每一台设备都必须入库,销售部门可从仓库提取设备供应客户。设备的入库和出库都必须借助运输工具。现只有一台运输工具,每次只能运输一台设备。请设计一个能协调工作的自动调度管理系统。
semaphore empty,full,S;
void main(){
empty = 10;
full = 0;S = 1; 
parbegin(in(),out());
}
in(){
	do{
		生产了一台设备;
		P(empty);
		P(S);
		使用运输工具入库;
		v(S);
		v(full);
	}while(1)
}
out(){
	do{
		P( full);
		P( S);
		使用运输工具出库;
		V(S);
		V( empty);
		提供设备供应客户;
	}while(1)
}

三、第四节-进程同步-经典算法小结

  1. 生产者-消费者问题
    共享缓冲区-多个生产者进程、多个消费者进程
  • 进程间的关系:
    互斥:多个进程间互斥使用同一个缓冲池;
    同步:当缓冲池空时,消费者必须阻塞等待;当缓冲池满时,生产者必须阻塞等待。
  • 设置信号量:
    Mutex:用于访问缓冲池时的互斥,初值是1
    Full:“满缓冲”数目,初值为0;
    Empty:“空缓冲"数目,初值为K。full+empty=K
  • 算法描述:
    生产者:首先判断缓冲区是否有空,如果有空再判断缓冲区的是否正在使用,若空闲则进行生产操作。操作完成后,需要及时释放缓冲区的使用权,以及对缓冲区“满缓冲”的数目进行更改,提示消费者进程进行消费操作。
  • 简易伪代码:
semaphore mutex = 1;//互斥信号量
semaphore empty = k;//缓冲区“空”数目
semaphore full = 0;//缓冲区“满”数目
program producer:
	wait(empty);
	wait(mutex);
	buffer操作;
	signal(mutex);
	signal(full);
program consumer:
	wait(full);
	wait(mutex);
	buffer操作;
	signal(mutex);
	signal(empty);
  • 需要注意:代码中wait操作顺序不可更改;signal可以更改,但会占用资源,还是尽早释放较好。
  1. 哲学家进餐问题
  • 问题描述:有五个哲学家坐在一张圆桌旁,在圆桌上有五个盘子有五只筷子,他们的生活方式就是交替地进行思考和进餐。平时,一个哲学家进行思考,饥饿时取其左右两只筷子,只有拿到这两只筷子时才能进餐;进餐完毕,放下筷子继续思考。
  • 解决思路:
    设置信号量:semaphore chopstick[0…4];
    第一种:每个人都先拿左手边的筷子再拿右手边的筷子,都拿到之后开始进餐。【此种方法若五人同时拿筷子,就会产生死锁】
    第二种:给每个哲学家以及筷子编号,奇数号哲学家拿右手边的筷子,偶数号哲学家拿左手边的筷子。
    第三种:限制四个人进行第一种算法思路,保证至少有一个人能顺利进餐。附加设置信号量semaphore sm = 4限制人数为4。
program  philosopher(i){
	wait(sm);
	wait(chopstick[i]);
	wait(chopstick[(i+1)mod 5]);
	eating;
	signal(chopstick[i]);
	signal(chopstick[(i+1)mod 5]);
	signal(sm);
}
  1. 读者-写者问题
  • 进程间的关系:
    当有写者在写数据时,其他写者和读者必须等待;
    当有读者在读数据时,其他写者必须等待;但其他读者可以同时读数据。
  • 信号量设置:
    信号量wmutex表示“允许写”,写者与其他进程互斥使用数据;
    公共整形变量Readcount表示“正在读”的读者数;
    信号量Rmutex:实现多个读者对Readcount的互斥操作;
  • 算法描述一(读者优先):
    写者:判断是否允许写,若允许则写入内容,完成后释放互斥信号量。
    读者:首先去判断rmutex是否被其他进程使用,若没有则进一步判断,使用if分支。
    若为0,则表示当前无读者在读,故判断wmutex信号量是否被使用,即是否有写者在写,若没有则占用数据,及时增加读者数量后也需要及时释放对rmutex的使用权,方便其他读者读取;再进一步判断当前读者是否为最后一位读者,若为最后一位则可以释放wmutex信号量。首先获取rmutex的使用权,对读者数量减一,若减一后为0,则为最后一位,相应的释放wmutex信号量,否则只能释放rmutex信号量,结束此轮进程判断。
  • 简易伪代码:
wmutex:semaphore = 1;//读者与写者之间、写者与写者之间互斥使用共享数据
readcount: int = 0;//当前正在读的读者数量
rmutex:semaphore =  1://多个读者互斥使用readcount
void writer{
	while(1){
		wait(wmutex);
		writing...
		signal(wmutex);
	}
}
void reader{
	while(1) {
		wait(rmutex)
		if readcount=0
			then wait(wmutex);
		readcount++;
		signal(rmutex);
		reading...
		wait(rmutex);
		readcount--;
		if readcount=0
			then signal(wmutex);
		signal(rmutex);
	}
}
  • 算法描述二(写者优先)
  • 简易伪代码:
semaphore wmutex = 1//读者与写者之间、写者与写者之间互斥使用共享数据
Semaphore S = 1//当至少有一个写者准备访问共享数据时,它可使后续的读者等待写完成
Semaphore S2 = 1//阻塞第二个以后的等待读者
int Readcount,writecount = 0,0;//当前读者数量、写者数量
Semaphore mutex1 = 1//多个读者互斥使用readcount
Semaphore mutex2 = 1//多个写者互斥使用writecount
Reader() {
	while(1){
		wait(S2);
		wait(S);
		wait(mutex1);
		if readcount=0
			then wait(wmutex);
		readcount++;
		signal(mutex1);
		signal(S);
		signal(S2);
		reading...
		wait(mutex1);
		readcount--;
		if readcount=0
			then signal(wmutex);
		signal(mutex1);
	}
}
void writer() {
	while(1)
		wait(mutex2);
		if writecount=0
			then wait(S);
		writecount++;
		signal(mutex2);
		wait(wmutex);
		writing...
		signal(wmutex);
		wait(mutex2);
		writecount--;
		if writecount=0
			then signal(S);
		signal(mutex2);
	}
}
  1. 理发师问题
  • 信号量设置:
    int waiting;表示坐在等候椅上的顾客数
    Cust_ready:理发椅上的顾客数;阻塞理发师
    Finished:顾客是否已完成理发
    mutex:互斥访问waiting
    chair:空闲的理发椅数量
  • 算法描述:
    理发师:首先判断是否有顾客在理发椅上等候,若有则进行理发,完成操作后提醒finished。
    顾客:首先获取waiting的使用权,判断等候椅是否满了,若满了则释放waiting的使用权离开;若没满,则更改waiting的值,并释放使用权。之后判断理发椅是否被使用,若空闲则坐上理发椅,重复获取waiting的使用权并更改waiting的值,记得及时释放。再通过cust_ready释放信号告诉理发师可以理发,理发师进行操作后,等待理发师通过finished信号量告诉顾客理发完成,最后离开理发椅,及时释放理发椅的使用权。
  • 简易伪代码:
int waiting;
semaphore cust_ready,finished,mutex,chair;
void main() {
waiting = 0;
cust_ready = finished = 0;
mutex = chair=1;
parbegin(barber,customer-i);
void  barber() {
	do {
		wait(cust_ready);
		cut_hair;
		signal(finished);
	}while(1);
}
void  customer-i (){
	wait(mutex);
	if(waiting < n) {
		waiting=waiting+1;
		signal(mutex);
	}else {
		signal(mutex);
		离开理发店;
		return;
	}
	wait(chair);
	sit_in_chair;
	wait(mutex);
	waiting=waiting-1;
	signal(mutex);     
	signal(cust_ready);
	get-haircut;
	wait(finished);
	stand_from_chair;
	signal(chair);
}
  • 7
    点赞
  • 53
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
操作系统中的PV操作是指进程之间通过信号量来实现同步互斥的一种机制。PV操作主要包括信号量的P操作和V操作。 P操作又称为申请操作。当进程需要使用一个资源时,它需要执行P操作。P操作会检查该资源的信号量值,若值大于0,则表示资源可用,进程可以继续执行,并将信号量值减1;若值等于0,则表示资源不可用,进程需要等待。 V操作又称为释放操作。当进程释放一个资源时,它需要执行V操作。V操作会将该资源的信号量值加1。如果有其他进程正在等待该资源,V操作会唤醒其中一个进程,使其继续执行。 下面通过一个简单的例子来说明PV操作的使用: 假设有两个进程P1和P2,它们都需要访问一个临界资源,同时只能有一个进程访问该资源。 1. 初始化一个二进制信号量sem,初始值为1,表示资源可用。 2. P1进程执行时,先执行P操作,检查sem的值。由于sem的值为1,P1可以继续执行,sem的值变为0,表示资源已被占用。 3. P1进程访问资源进行操作。 4. P1进程操作完成后,执行V操作,将sem的值加1。由于没有其他进程等待该资源,操作结束。 5. P2进程执行时,先执行P操作,检查sem的值。由于sem的值为1,P2可以继续执行,sem的值变为0,表示资源已被占用。 6. P2进程访问资源进行操作。 7. P2进程操作完成后,执行V操作,将sem的值加1。由于没有其他进程等待该资源,操作结束。 通过PV操作的使用,可以实现进程之间的同步互斥。只有当资源可用时,进程才能访问该资源,否则需要等待。这样可以有效避免进程之间的冲突和竞争。对于并发程序的正确执行具有重要意义。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值