PV和管程 操作系统教程课后习题
- 有一个电子转帐系统共管理 10000 个帐户,为了向客户提供快速转帐业务, 有许多并发执行的资金转帐进程,每个进程读取一行输入,其中,含有:贷方帐 号、借方帐号、借贷的款项数。然后,把一款项从贷方帐号划转到借方帐号上, 这样便完成了一笔转帐交易。写出进程调用 Monitor ,以及 MOnitor 控制电子 资金转帐系统的程序。
TYPE lock-account = monitor
VAR use : array [1 … 10000] of Boolean ; / *该帐号是否被锁住使用标志
S :array [ 1 … 10000 ] of condition ; / *条件变量
DEFINE lockaccount unlockaccount / *移出过程
USE wait , signal , check , release ; / *移入过程
begin
for i:= 1 ; to 10000 do use [i]:=false ;
end .
procedure lockaccount ( var i,j : integer ){
Check ( IM )
if i > j then begin
Temp:= i ;
i : = j ;
j : = temp ;
end ; / *层次分配,先占号码小的账号否则可能产生死锁
if use [i]
wait(s[i].lockaccount,IM ) ;
else
use [ i ] :=true ; / *锁住 account ( i )
if use[j]
wait ( s[j].lockaccount,IM);
else
use [j]:=true ; / *锁住 accounto )
Release ( IM ) ;
}
Proeedure unfockaccount ( var i:sinteger ; ){
Check ( IM ) ;
use [ i ] : = false ;
signal(s[i].lock-account , IM ) ;
Release ( IM ) ;
}
Process transfer account{
begin
input a information line ;
get the account number i,j and 还款数 x ;
Lock-account.lockaccount ( i,j )
按锁住帐号 account ( i )和 account(j)执行;
A [j]:= A [j] - x ;
A [i]:=A [i] + x ;
Lock-ccount.unlockaccount(i);
Lock-account.unlockaccount(j);
end ;
}
- 有
n
个进程将字符逐个读入到一个容量为80
的缓冲区中(n>1)
,当缓冲区满后,由输出进程Q
负责一次性取走这80
个字符。这种过程循环往复,请用信号量和P、V操作写出n个读入进程(P1, P2,…Pn)
和输出进程Q
能正确工作的的动作序列
semaphore empty = 80; // 空闲缓冲区的数量
semaphore full = 0; // 缓冲区是否满
semaphore mutex = 1; // 互斥信号量,保证count,int等能完整执行
int count = 0; // 表示已写入内容的缓冲区的大小
char[80] Buffer; // 缓冲区
int in = 0; // 缓冲区读入游标-读入位置标志位
cobegin
process Pi(i=1,2,...,n) {
while(true) {
{读入一个字符到x};
P(empty);
P(mutex);
Buffer[in] = x;
in = (in + 1) % 80;
count++;
if(count == 80) {
count = 0; // 从0开始继续计数
V(mutex);
V(full); // 读入满80个字符后提醒Q进程取走
} else
V(mutex);
}
}
process Q {
while(true) {
P(full);
P(mutex);
for(int j=0; j<80; j++)
read Buffer[j];
in = 0;
V(mutex);
for(int j=0; j<80; j++)
V(empty);
}
}
coend
- 某大型银行办理人民币储蓄业务,由n个储蓄员负责。每个顾客进入银行后先至取号机取一个号,并且在等待区找到空沙发坐下等着叫号。取号机给出的号码依次递增,并假定有足够多的空沙发容纳顾客。当一个储蓄员空闲下来,就叫下一个号。
var customer_count, server_count, mutex: semaphore;
customer_count:=0; server_count:=n;
mutex:=1;
process customeri(i=1,2,….)
begin
take a number;
P(mutex);
等待区找到空沙发坐下;
V(mutex);
V(customer_count);
P(server_count);
end;
Process servers j(j=1,2,3,…)
Begin
L: P(customer_count);
P(mutex); //涉及到叫下一个号的问题,必须保证原子性
被呼号顾客离开沙发走出等待区;
V(mutex);
为该号客人服务;
客人离开;
V(server_count);
go to L;
end;
理发师问题
理发店理有一位理发师、一把理发椅和n把供等候理发的顾客坐的椅子
如果没有顾客,理发师便在理发椅上睡觉
一个顾客到来时,它必须叫醒理发师
如果理发师正在理发时又有顾客来到,则如果有空椅子可坐,就坐下来等待,否则就离开
int waiting=0; //等候理发顾客坐的椅子数
int CHAIRS=N; //为顾客准备的椅子数
semaphore customers, barbers, mutex;
customers=0; barbers=0; mutex=1;
process barber( ) {
while(true) {
P(customers);
//有顾客吗?若无顾客,理发师睡眠
P(mutex);
//若有顾客时,进入临界区
waiting--; //等候顾客数少一个
V(barbers); //理发师准备为顾客理发
V(mutex); //退出临界区
cut_hair();
//理发师正在理发(非临界区)
}
}
process customer_i( ) {
P(mutex); //进入临界区
if(waiting<CHAIRS) {
//有空椅子吗
waiting++; //等候顾客数加1
V(customers); //唤醒理发师
V(mutex); //退出临界区
P(barbers);
//理发师忙,顾客坐下等待
get_haircut(); //否则顾客坐下理发
}
else V(mutex); //人满了,走吧!
}
-
今有k个进程,它们的标号依次为1、2、…、k,如果允许它们同时读文件file,但必须满足条件:参加同时读文件的进程的标号之和需小于M(k<M),请使用:1)信号量与P、V操作,2)管程,编写出协调多进程读文件的程序。
1) 使用信号量与P、V操作 semaphore waits,mutex; int numbersum=0; wait=0;mutex=1; cobegin process readeri(int number) { //i=1,2,… P(mutex); while(numbersum+number>=M) {V(mutex);P(waits);} numbersum=numbersum+number; V(mutex); Read file; P(mutex); numbersum=numbersum-number; V(waits); V(mutex); } 自写: process readeri(int number) { //i=1,2,… P(mutex); while (numbersum + number >= M) { P(waits); } numbersum = numbersum + number; V(mutex); Read file; P(mutex); numbersum = numbersum - number; V(waits); V(mutex); } coend
-
假设一个录像厅有0,1,2三种不同的录像片可由观众选择放映。录像厅的放映规则为:
1)任何时刻最多只能放映一种录像片,正在放映的录像片是自动循环放映的。最后一个观众主动离开时结束当前录像片的放映。
2)选择当前正在放映录像片的观众可立即进入,允许同时有多位选择同一中录像片的观众同时观看,同时观看的观众数量不受限制。
3)等待观看其他录像片的观众按到达顺序排队,当一种新的录像片开始放映时,所有等待观看该录像片的观众可一次进入录像厅同时观看。semaphore mutex=1,mutex0=1,mutex1=1,mutex2=1; int count0=0,count1=0,count2=0; void zero() { P(mutex0); if(count0=0) P(mutex); count0++; V(mutex0); 观影; P(mutex0); count0--; if(count0=0) V(mutex); V(mutex0); } void one() { P(mutex1); if(count1=0) P(mutex); count1++; V(mutex1); 观影; P(mutex1); count1--; if(count1=0) V(mutex); V(mutex1); } void two() { P(mutex2); if(count2=0) P(mutex); count2++; V(mutex2); 观影; P(mutex2); count2--; if(coun2=0) V(mutex); V(mutex2); } void main() { cobegin zero();one();two(); coend }
管程实现磁盘调度的电梯调度算法
Type diskhead = MONITOR
VAR bus:boolean;
headpos:0..199;
direction:(up,down);
cylinder:Array[0..199] of condition;
count:Array[0..199] of integer;
Define require, release;
Procedure require(dest:0..199)
Being
If busy Then
Begin
count[dest]:=count[dest] + 1;
wait(cylinder[dest]);
End
busy:=true;
If dest < headpos Then
direction:=down;
Else
If dest > headpos Then
direction:=up;
headpos:=dest
End;
Procedure upscan;
Var I:0..200;
flag:(false,true);
Begin
I:=headpos;
flag:=false;
While (I <= 199) and (count[I] = 0) Do
I:=I + 1;
If I<=199 Then
Begin
count[I]:=count[I] - 1;
signal(cylinder[I]);
flag:=true;
End
End;
Procedure downscan;
Var I:-1..199
flag:(false, true);
Begin
I:=headpos;
flag:=false;
While (I >= 0) and (count[I] = 0) Do
I:=I - 1;
if I >= 0 Then
Begin
count[I]:=count[I] - 1;
signal(cylinder[I]);
flag:=true;
End
End;
Procedure release;
Begin
busy:=false;
If direction = up Then
Begin
upscan;
If (!flag) Then
downscan;
End
Else
Begin
downscan;
If (!flag) Then
upscan;
End
End;
Procedure initialize;
Var I:0..199;
Begin
busy:=false;
headpos:=0;
direction:=up;
For I:=0 To 199 Do
count[I]:=0
End
Begin initialize End;
飞机票问题
Var A : ARRAY[1..m] of integer;
mutex : semaphore;
mutex:= 1;
cobegin
process Pi
var Xi:integer;
begin
按旅客定票要求找到A[j];
P(mutex);
Xi := A[j];
if Xi>=1 then
begin
Xi:=Xi-1;A[j]:=Xi;
V(mutex); {输出一张票};
end;
else begin
V(mutex); {输出“票已售完”};
end;
goto L1;
end;
coend
独木桥问题
详见 独木桥问题
其他课后习题
`