操作系统PV原语文档格式.docx
《操作系统PV原语文档格式.docx》由会员分享,可在线阅读,更多相关《操作系统PV原语文档格式.docx(32页珍藏版)》请在冰豆网上搜索。
p1();
p2();
p3();
p4();
p5();
p6();
coend
}
P1()
其他语句;
V(f1);
P2()
P(f1);
V(f2);
P3()
V(f3);
P4()
P(f2);
V(f4);
P5()
V(f5);
P6()
P(f3);
P(f4);
P(f5);
V(f6);
本题写的是完整代码,多数情况下只需要写过程,过程多数属于循环动作,采用死循环。
P、V操作主要用于互斥和同步。
互斥属于间接制约,受资源数量限制;
同步属于直接制约,用于控制各过程的前后次序。
2.生产者-消费者问题
一个生产者和一个消费者之间只有同步关系,多个生产者之间还需要用到互斥,多个消费者之间也需要用到互斥
代码如下
存在空单元才可以生产(有地方存),存在满单元才可以消费(有库存取)。
信号量avail代表缓冲区中空单元数量,初值可设为n;
full表示满单元数量,初值可设为0;
mutex用于互斥,初值为1。
生产者过程
Deposit():
Begin
P(avail)
P(mutex)
送数据入缓冲区某单元
V(mutex)
V(full)
end
消费者过程
remove():
P(full)
取缓冲区某单元数据
V(avail)
这两个过程在这里只执行了一次,也可以视题意放在死循环里(多数情况是循环生产和消费)。
另外要注意P操作要考虑次序,用于互斥的P操作多数情况下放后面(不绝对,要自己分析)。
本题中若颠倒次序,会发生死锁(消费者先抢到mutex资源,却没有满单元,生产者虽然有空单元,但却卡在前面对mutex的请求上)
3.读写者问题
多个进程可以同时读某数据(此时不可写),只允许一个进程写数据(此时不可读)。
代码如下:
rc是全局变量,代表读者人数,初值为0;
db是信号量,代表允许写,初值为1(只允许1个人写);
mutex是信号量,对全局变量要互斥操作,因此使用mutex,初值为1;
读者人数达到1就不可写,读者人数为0时可写。
reader():
begin
L1:
P(mutex)
rc=rc+1
if(rc==1)thenp(db)
v(mutex)
读操作
rc=rc-1
if(rc==0)thenv(db)
GotoL1
writer():
L2:
P(db)
写操作
V(db)
GotoL2
以上代码中,如果一直有人在读,那么写永远没有机会,因此可以增加一个信号量w,初始值为1,代表允许新读者进入,这样当有人想执行写时,就不再允许新读者进入,旧读者总有读完离开的时候,这样写就有机会得到执行。
P(w)
v(w)
V(w)
4.哲学家用餐问题
五个哲学家围成一圈,五根筷子放在每人两侧,拿到两根筷子的可以用餐,没拿到足够筷子的只能等别人吃完放下筷子才能得到足够的筷子。
如果不考虑死锁,每个哲学家的用餐过程如下(i表示哲学家的号码(0-4),左手边筷子号为i,右手边筷子号为(i+1)%5,每个筷子都是资源,用信号量表示),i表示哲学家序号,则每人代码如下
pp(i)
p(stick[i])//拿左边筷子
p(stick[(i+1)%5])//拿右边筷子
用餐
V(stick[i])
V(stick[(i+1)%5])
End
根据实际情况,吃饭过程可以不用死循环。
如果程序写成这样,则存在每个人都拿到左边筷子的死锁情况,预防死锁只要破坏以下4条中的1条:
1.互斥2.允许部分分配3.不剥夺4.循环等待
给资源分先后等级(必须先取得等级高的资源,才能去申请下一等级资源),就可以破坏循环等待条件,从而避免死锁。
本题可以让偶数号码的哲学家先申请左手筷子,再申请右手筷子;
让奇数号码的哲学家先申请右手筷子,再申请左手筷子。
这样五跟筷子中的0,2,4成了五个人第一步抢夺的筷子,抢到者才能继续申请1,3,把筷子分成两个等级,从而避免了死锁
if(imod2==0)thenbegin
p(stick[i])//拿左边筷子
end
else
p(stick[(i+1)%5])//拿右边筷子
end
用餐
5.理发师问题
理发馆有1把理发用的椅子,5把等待座椅,顾客进来后如果没人就坐到理发椅上,有人正在理发就坐到等待椅上,如果等待椅也满了就直接离开。
理发师看到理发椅上坐了人就理发,顾客理发完毕就离开。
描述理发师和顾客的行为。
分析顾客和理发师的行为
顾客:
理发师:
(属于循环动作)
顾客数>
=6则离开
否则顾客数+1
申请等待椅
申请理发椅
释放等待椅
发现有人坐到理发椅并准备好,就开始理发,告知理发完毕
释放理发椅
离开(顾客数-1)
定义全局变量waiting,用于统计顾客人数,初值为0;
定义信号量mutex,对waiting进行操作时起互斥作用,初值为1;
定义信号量bchair表示理发椅个数,初值为1;
定义信号量wchair表示等待椅个数,初值为5;
定义信号量ready表示顾客坐到理发椅后准备好理发,初值为0;
定义信号量finish表示理发完毕,初值为0。
Barber():
P(ready)
理发
V(finish)
End
Customers():
L1:
//这里用死循环表示不断有顾客来
If(waiting<
6)thenbegin
Waiting+=1
V(mutex)
Elsebegin
Return//(离开)
P(wchair)//申请等待椅
P(bchair)//申请理发椅
V(wchair)//申请到理发椅后释放等待椅
V(ready)//向理发师发出准备好信号
P(finish)//收到理发师理发完毕信号
V(bchair)//释放理发椅
Waiting-=1
Return//(离开)
GotoL1
7.P1、P2、P3互斥使用一个N单元的缓冲区,P1用produce()生成一个正整数,用put(x)把该数放入缓冲区某一空单元;
P2用getodd()从缓冲区取出一个奇数,用countodd()统计奇数个数;
P3用geteven()从缓冲区取出一个偶数,用counteven()统计偶数个数,写出P1、P2、P3。
P1、P2、P3显然和生产者-消费者问题类似,有一个生产者,两个消费者,消费产品的类型不同,因此生产时也要区分产品类型,并且这3个进程可以写成死循环。
定义信号量empty,表示空单元个数,初值为N;
定义信号量odd表示放奇数单元的个数,初值为0;
定义信号量even表示放偶数单元的个数,初值为0;
定义信号量mutex,用于实现缓冲区互斥,初值为1。
P1():
x=produce()
p(empty)
p(mutex)
put()
v(mutex)
ifx%2=1thenv(odd)
elsev(even)
gotoL1
P2():
L2:
P(odd)
Getodd()
v(empty)
countodd()
gotoL2
P3():
L3:
P(even)
Geteven()
counteven()
gotoL3
8.过桥者问题,
同方向可上桥,桥上最多可容纳3个人。
过桥问题类似读写者问题,读写者是一方为多个读者,一方为一个写者,而过桥问题相当于把读者分两组,同组的可进入同时阅读。
定义全局变量easten,westen分别表示桥上从东往西和从西往东的人数,初值为0;
定义信号量meast,mwest分别用于桥东头和桥西头用于统计人数时进行互斥,初值均为1;
桥上无人时两边不能同时上桥,因此定义信号量wait,用于互斥,初值为1;
定义信号量count,用于限制桥上人数,初值为3。
以下为桥两端每个过桥者行为的代码:
easttowest():
P(wait)
P(meast)
easten=easten+1
if(easten==1)thenp(mwest)//桥上只要有一个从东往西的,则禁止西桥头的人上桥
v(meast)
v(wait)
p(count)
东->
西
V(count)
P(meast)
easten=easten-1
if(easten==0)thenv(mwest)//桥上没有从东往西的人,则允许西桥头的人上桥
另一端程序如下,与之类似
westtoeast():
P(mwest)
westen=westen+1
if(westen==1)thenp(meast)
v(mwest)
西->
东
v(count)
P(mwest