操作系统---PV操作题分析

1.某寺庙有小和尚、老和尚若干,有一水缸,由小和尚提水入缸供老和尚饮用。水缸可容10桶水,水取自同一井中。水井径窄,每次只能容一个桶取水。水桶总数为3个。每次入缸取水仅为1桶水,且不可同时进行。试给出有关从缸取水、入水的算法描述。

从井中取水并放入水缸是一个连续的动作,可视为一个进程;从缸中取水可视为另一个进程。设水井和水缸为临界资源,引入 well 和 vat:三个水桶无论是从井中取水还是将水倒入水缸都是一次一个,应该给它们一个信号量pail,抢不到水桶的进程只好等待。水缸满时,不可以再放水,设置 empty 信号量来控制入水量;水缸空时,不可以取水,设置 full 信号量来控制。本题需要设置5个信号量来进行控制:

semaphore well=1;        //1个水井

semaphore vat=1;        //1个水缸

pail=3;        //3个水桶

empty=10;        //水缸中的剩余空间能容纳的水的桶数,初值为10

full=0;        //表示能从水缸中取走的水的桶数,初始水缸没水,处值为0

//小和尚

while(1){

        P(empty);        //检查水缸里能不能放水

        P(pail);        //能放水,则拿桶,桶-1

        P(well);        //到井中打水

        从井中打水;

        V(well);        //打完水,释放“井”互斥资源

        P(vat);        //将水倒入缸中

        将水倒入缸中;

        V(vat);        //倒完后,释放“水缸”互斥资源

        V(full);        //缸中水的桶数+1

        V(pail);        //使用完桶放回,桶+1

}

//老和尚

while(1){

        P(full);        //检查水缸中是否有水

        P(pail);        //拿桶装水

        P(vat);        //使用“水缸”互斥资源

        从缸中取水;

        V(vat);        //释放互斥资源

        V(empty);   //水缸中的剩余空间+1

        喝水;       

        V(pail);        //把桶放回

}

2.如下图所示,三个合作进程P1,P2,P3,它们都需要通过同一设备输入各自的数据a,b,c,该输入设备必须互斥地使用,而且其第一个数据(a)必须由P1进程读取,第二个数据(b)必须由P2进程读取,第三个数据(c)必须由P3进程读取。然后,三个进程分别对输入数据进行下列计算:

最后,P1进程通过所连接的打印机将计算结果x,y,z的值打印出来。请用信号量实现它们的同步。

分析:

进程P1需要用到进程P1读取的a,进程P2读取的b:x=a+b

进程P2需要用到进程P1读取的a,进程P2读取的b:y=a*b

进程P3需要用到进程P2计算的结果y,进程P3读取的数据c,以及进程P1读取的数据a

所以:

P1进程在计算前,需要先确保已经输入了b,其他同理。

这里我们设置S1,S2,S3三个信号量,并将S1初值设为1,S2,S3初值设为0,这样就不用为输入设备专门设置互斥信号量了。但是这样设置就是默认三个进程中P1最先执行。信号量Sb,Sy,Sz分别表示是否已经输入b,以及y,z是否已经计算完成。Sb,Sy,Sz初值为0

P1(){

        P(S1);        //使用输入设备

        输入数据a;

        V(S2);        //S2+1,表示接下来P2可以使用输入设备

        P(Sb);        //检查数据b有没有输入

        x=a+b;

        P(Sy);        //检查y是否完成计算

        P(Sz);        //检查z是否完成计算

        使用打印机打印出x,y,z的结果;

}

P2(){

        P(S2);

        输入数据b;

        V(S3);        //S3+1,表示接下来P3可以使用输入设备

        V(Sb);        //表示b已经输入,可以正常进行P(Sb)了

        y=a*b;

        V(Sy);       //Sy已经计算完成,可以正常执行P(Sy)了

}

P3(){

        P(P3);

        输入数据c;

        P(Sy);        //检查y是否已经计算完成

        z=y+c-a;

        V(Sz);        //可以执行P(Sz)

}

注意几点:

(1) 为什么P2,P3进程计算之前不需要P(S1)了,因为设置初值的时候我们把P1=1,P1最先执行,数据a最先输入,所以不需要检查数据a有没有输入

(2) 而P1执行时,就需要先检查b是否已经输入,即P(S2),所以进程实际执行的顺序:

① P1进程执行到P(Sb),发现Sb=0,不能继续往下执行

② 执行P2进程,P2进程V(Sb)

③ P1进程继续执行,直到P(Sz),Sz=0,堵塞

④ 执行P3进程,V(Sz)

⑤ P1继续执行

总之就是先V后P,一定要先V资源后,才能P资源

3.有桥如下图所示。车流方向如箭头所示。回答如下问题:

(1)假设桥上每次只能有一辆车行驶,试用信号灯的PV操作实现交通管理。

semaphore bridge=1;

NtoS(){

        P(bridge);

        通过桥;

        V(bridge);

}

StoN(){

        P(bridge);

        通过桥;

        V(bridge);

}

(2)假设桥上不允许两车交会,但允许同方向多辆车一次通过(桥上可有多辆同方向行驶的车)。试用信号灯的PV操作实现桥上的交通管理。

桥上可以同方向多车行驶,需要设置 bridge,还需要对同方向车辆计数。为了防止同方向计数中同时申请 bridge 造成同方向不可同时行车的问题,要对计数过程加以保护,因此设置信号量mutexSN和mutexNS。

int countSN=0;        //从南向北的汽车数量

int countNS=0;        //从北向南的汽车数量

semaphore mutexSN=1;        //保护countSN

semaphore mutexNS=1;        //保护countNS

semaphore bridge=1;        //互斥信号量

StoN(){               //从南向北的汽车

        P(mutexSN);

        if(countSN==0)

                P(bridge);

        countSN++;

        V(mutexSN);        

        过桥;

        P(mutexSN);

        countSN--;

        if(countSN==0)

                V(bridge);

        V(mutexSN);

}

NtoS(){        //从北向南的汽车

        P(mutexNS);

        if(countNS==0)

                P(bridge);

        countNS++;

        V(mutexNS);        

        过桥;

        P(mutexNS);

        countNS--;

        if(countNS==0)

                V(bridge);

        V(mutexNS);

}

以StoN为例,若这里没有设置mutexSN,如果有多辆自南向北的车同时经过桥,那么都会检测到countSN=0,并且P(bridge),而bridge=1,只有1辆车能申请到bridge,其他车则不能经过桥,达不到题目的要求。

        if(countSN==0)

                P(bridge);

        countSN++;

加入mutexSN:mutexSN=1,若有多辆自南向北的车同时经过桥,一辆车能成功执行P(mutexSN)并申请(bridge),成功记录该车后(countSN++),其他自南向北的车进程就会跳过if判断,不会被堵塞在P(bridge)。

        P(mutexSN);

        if(countSN==0)

                P(bridge);

        countSN++;

        V(mutexSN);      

4.假设一个录像厅有 1,2,3 三种不同的录像片可由观众选择放映,录像厅的放映规则如下:

1)任意时刻最多只能放映一种录像片,正在放映的录像片是自动循环放映的,最后一名观众主动离开时结束当前录像片的放映。

2)选择当前正在放映的录像片的观众可立即进入,允许同时有多位选择同一种录像片的观众同时观看,同时观看的观众数量不受限制。

3)等待观看其他录像片的观众按到达顺序排队,当一种新的录像片开始放映时,所有等待观看该录像片的观众可依次序进入录像厅同时观看。用一个进程代表一个观众要求:用信号量方法 PV操作实现,并给出信号量定义和初始值。

电影院一次只能放映一部影片,希望观看的观众可能有不同的爱好,但每次只能满足部分观众的需求,即希望观看另外两部影片的用户只能等待。分别为三部影片设置三个信号量s0,s1,s2初值分别为1、1、1。电影院一次只能放一部影片,因此需要互斥使用。由于观看影片的观众有多个,因此必须分别设置三个计数器(初值都是0),用来统计观众个数。当然,计数器是个共享变量,需要互斥使用。

semaphore s=1,s0= 1,s1= 1,s2= 1;        //s保证了一次只放一部影片

int count0=0,count1=0,count2=0;        //看第一部影片的观众
process videoshow1 {
        P(s0);       

//设置P(s0)/V(s0),保证了计数的互斥性,防止同时申请s信号量的观众,不能同时观看影片
        count0=count0+1;
        if(count0==1)       

//如果是第1位观看第1部影片的观众,则为他分配互斥信号量s,后面来的观众就不需要P(s)了,因为已经在放映第1部影片了
                P(s);
        V(s0);
        看影片;
        P(s0) ;        

        count0=count0-1;

        if(count0==0)        //没人看了,就结束放映
                V(s);        //释放互斥信号量s,这样其他影片就可以放映了
        V(s0);

}

process videoshow2 {
        P(s1);   
        count1=count1+1;
        if(count1==1)       
                P(s);
        V(s1);
        看影片;
        P(s1) ;        

        count1=count1-1;

        if(count1==0)        //没人看了,就结束放映
                V(s);      
        V(s1);

}

process videoshow3 {
        P(s2);   
        count2=count2+1;
        if(count2==1)       
                P(s);
        V(s2);
        看影片;
        P(s2) ;        

        count2=count2-1;

        if(count2==0)        //没人看了,就结束放映
                V(s);      
        V(s2);

}

提示:这道题和第3题思路是类似的

5.设公共汽车上驾驶员和售票员的活动分别如下图所示。驾驶员的活动:启动车辆,正常行车,到站停车;售票员的活动:关车门,售票,开车门。在汽车不断地到站、停车、行驶的过程中,这两个活动有什么同步关系?用信号量和P,V操作实现它们的同步。

在汽车行驶过程中,驾驶员活动与售票员活动之间的同步关系为:售票员关车门后,向驾驶员发开车信号,驾驶员接到开车信号后启动车辆,在汽车正常行驶过程中售票员售票,到站时驾驶员停车,售票员在车停后开门让乘客上下车。因此,驾驶员启动车辆的动作必须与售票员关车门的动作同步;售票员开车门的动作也必须与驾驶员停车同步。应设置两个信号量S1,S2:

S1表示是否允许驾驶员启动汽车(初值为0);S2表示是否允许售票员开门(初值为0)。

semaphore S1=0,S2=0;

Procedure driver

{
        while(1)

        {
                P(S1);        //检查是否允许驾驶员启动汽车,即P(S1)=1

                Start;        //启动汽车

                Driving;
                Stop;
                V(S2);        //停车后允许售票员开门

        }

}

Procedure Conductor

{
        while(1)

        {
                关车门;
                V(s1);        //允许驾驶员开车
                售票;
                P(s2);        //检查是否允许售票员开门,即P(S2)=1

                开车门;
                上下乘客;

        }

}

### 关于信号量PV操作在生产者消费者问题中的应用 #### 使用信号量解决打印机资源共享问题 当涉及到共享资源如打印机时,可以利用信号量机制来协调多个进程对该资源的访问。下面是一个基于信号量的解决方案,用于处理多线程环境下的打印任务调度。 ```c #include <stdio.h> #include <pthread.h> // 定义信号量变量 sem_t mutex; sem_t printer_available; void *producer(void *arg) { int item; while (1) { // 假设这里有一个函数用来创建新的打印请求 create_print_request(&item); sem_wait(&printer_available); // 测试是否有可用的打印机 sem_wait(&mutex); // 进入临界区之前先获取锁 printf("Producer produced %d\n", item); enqueue(item); // 将新产生的项目加入队列等待打印 sem_post(&mutex); // 释放锁离开临界区 sem_post(&printer_available); // 表明已经完成了一次打印准备动作 } } void *consumer(void *arg) { int consumed_item; while (1) { sem_wait(&mutex); // 获取锁进入临界区 if (!is_queue_empty()) { // 如果缓冲区内存在待打印项则继续执行 dequeue(&consumed_item);// 取出一项进行实际打印工作 printf("Consumer consumed %d\n", consumed_item); perform_printing(consumed_item); // 实际调用打印命令 sem_post(&mutex); // 结束本次打印后退出临界区并解锁 sem_post(&printer_available); // 向其他潜在使用者通知打印机再次变为可用了 } else { sem_post(&mutex); // 缓冲为空时不作任何改变直接返回 } } } ``` 这段程序展示了如何通过`P()`(即`sem_wait()`) 和 `V()` (即`sem_post()`) 来控制对有限数量打印机设备的竞争性访问[^1]。每当一个生产者想要提交一个新的打印作业给系统时,它会尝试减少名为`printer_available` 的计数器;而一旦某个消费者的打印过程结束,则增加这个计数器以允许下一个生产者开始其流程。同时,在每次修改共享数据结构(这里是假设存在的队列)前后都使用了互斥锁(`mutex`) 来防止竞争条件的发生[^3]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值