1.问答题:有一个文件F,有A,B两组进程共享这个文件,同组的进程可以同时读文件F,但当有A组(或B组)的进程在读文件F时就不允许B组(或A组)的进程读,
解:定义两个计数器C1,C2,分别记录A组和B组中读文件的进程数,三个信号量S1,S2,SAB,其中S1用于通知A组进程已经有B组进程在读文件F了,S2用于通知B进程已经有A进程在读文件F了,SAB用于实现对共享变量C1和C2以及临界区的互斥访问.
begin
var S1,S2,SAB:semaphore
=
1
,
1
,
1
;
C1,C2:integer
=
0
,
0
;
process A
-
i(i
=
1
,
2
)
begin
repeat
P(SAB);
C1
=
C1
+
1
;
if
(C1
=
1
) then P(S2);
V(SAB);
读文件F;
P(SAB)
C1
=
C1
-
1
;
if
(C1
==
0
)V(S2)
V(SAB)
until
false
end
process B
-
i(i
=
1
,
2
)
begin
repeat
P(SAB);
C2
=
C2
+
1
;
if
(C2
=
1
) then P(S1);
V(SAB);
读文件F;
P(SAB)
C2
=
C2
-
1
;
if
(C2
==
0
)V(S1)
V(SAB)
until
false
end
end
2,应用题:get进程读数据到buffer1里,然后进程copy从buffer1里的数据复制到buffer2里,再由put进程取出buffer2里的数据去进行打印.
分析:这是两个阶段的生产-消费问题.第一阶段的生产者和消费者是get和copy,第二阶段的生产者和消费者是copy和put.为简单计,假设buffer1,buffer2 都是单缓冲区,因此只要设4个信号量empty1,full1,empty2,full2,就可以了.
begin
buffer:integer
empty1,empty2,full1,full2,:semaphore
=
1
,
1
,
0
,
0
;
cobegin
process Get
begin
repeat
读数据
p(empty1);
把数据放到buffer1里
v(full1);
until
false
end
process Copy
begin
repeat
p(full1)
从buffer1里读出数据
v(empty1);
p(empty2)
把数据放到buffer2里
v(full2)
until
false
end
process Put
begin
repeat
p(empty2)
从buffer2里读出数据
v(full2);
打印数据
until
false
end
coend
end
3.输入进程输入数据到缓冲区buffer1中,计算进程从buffer1中读出数据进行计算,并把结果送入buffer2,然后打印进程从buffer2中读出结果进行打印.假设缓冲区大小分别为n1和n2.
begin
buffer:integer
empty1,empty2,full1,full2,mutex1,mutex2:semaphore
=
n1,n2,
0
,
0
,
1
,
1
;
cobegin
process Input
begin
repeat
输入数据
p(empty1);
p(mutex1);
把数据放到buffer1里
v(mutex1);
v(full1);
until
false
end
process Compute
begin
repeat
p(full1)
p(mutex1);
从buffer1里读出数据
v(mutex1);
v(empty1);
p(empty2)
p(mutex2);
把数据放到buffer2里
v(mutex2);
v(full2);
until
false
end
process Print
begin
repeat
p(empty2)
p(mutex2);
从buffer2里读出数据
v(full2);
v(full2);
打印数据
until
false
end
coend
end
4.过桥问题.
(1)桥每次只能有一辆车通过,
(2)不允许两车交会,但允许同方向的多辆车依次通过
解:(1)
begin
mutex:semaphore
=
1
;
cobegin
process Scar//南边来的车
begin
come;
p(mutex);
过桥;
v(mutex);
go;
end
process Ncar//北边来的车
begin
come;
p(mutex);
过桥;
v(mutex);
go;
end
coend
end
(2)
begi
var Smutex
=
1
,Nmutex
=
1
,mutex
=
1
:semaphore;
SCarCount
=
0
,NCarCount
=
0
:integer;
cobegin
process Scari(i
=
1
,
2
)
begin
p(Smutex);
if
(SCarCount
=
0
) then p(mutex);
SCarCount
=
SCarCount
+
1
;
v(Smutex);
过桥;
p(Smutex);
SCarCount
=
SCarCount
-
1
;
if
(SCarCount
=
0
) then v(mutex);
v(Smutex);
end
process Ncarj(j
=
1
,
2
)
begin
p(Nmutex);
if
(NCarCount
=
0
) then p(mutex);
NCarCount
=
NCarCount
+
1
;
v(Nmutex);
过桥;
p(Nmutex);
NCarCount
=
NCarCount
-
1
;
if
(NCarCount
=
0
) then v(mutex);
v(Nmutex);
end
coend
end
5.在管道通信机制中,用信号量描述读进程和写进程访问管道文件的过程,假设管道文件大小为10KB.
分析:在UNIX系统中,利用一个打开的共享文件来连接两个相互通信的进程,这个共享文件叫管道.作为管道输入的发送进程,以字符流的形式将信息送入管道,而作为管道输出的接收进程,从管道中获取信息.管道通信机制要提供三方面的协调能力:(1)互斥.当一个进程对管道进行读/写操作时,另一个进程必须等待.(2) 同步.当写进程把数据写入管道后便去睡眠等待,直到输出进程取走数据后唤醒它.若一次写入的数据超过缓冲区剩余空间的大小,当缓冲区满时,写进程必须阻塞,并唤醒读进程。(3)对方是否存在.只有确定对方存在时,才能够进行通信.
本题只需要考虑互斥,同步问题。由于只有一对进程访问管道,因此不需要设置互斥信号量,只要设置两个同步信号量empty,full.分别表示管道可写和可读.
begin
pipe:array[
0
9
] of kilobytes;
ts
=
10
,length,in
=
0
,out
=
0
:integer;
empty,full:semaphore
=
1
,
0
;
cobegin
process PipeWriter
begin
repeat
产生数据;
p(empty);
length
=
data length;
while
(length
>
0
and ts
>
0
)
begin
pipe[in]
=
data of 1KB;
in
=
(in
+
1
) mod n;
ts
=
ts
-
1
;
length
=
length
-
1
;
end
v(full);
end
process Consumer
begin
repeat;
p(full);
从缓冲区取出一件物品;
out
=
(out
+
1
) mod n;
ts
=
ts
+
1
;
v(empty);
end
coend
end