操作系统第2章习题分析
算法实现这个控制。
2.公交车行驶问题
void Driver () { do { 启动开车; 正常行车; 到站停车; } while(TRUE); }
void Conductor () { do { 开车门; 关车门; 卖票; } while(TRUE); }
信号量设置:用两个信号量s1、s2,分别表示可以 开门和可以开车,其初始值都为0。
1.单行隧道问题
分析:解决p2“饥饿”现象的方法:再设一个信号量k,让p1、p2排队,可 以做到p1方向比p2方向晚来的车辆被k阻止。 int c=0,m=1,sd=1,k=1; 问题: cobegin 1. 若P1过隧道,则后续车辆可以跟进; P1() // P2() 2. 若p2过隧道,一次只能过一辆 。 P1() coend P2() { P(k); P(sd); 通过隧道; V(sd); V(k); } { P(k); /* 与P2一起排队 */ P(m); /* m1控制计数器c */ if (c== 0 ) P(sd); /*P1第一辆车通过时占有隧道*/ c=c+1; V(m); V(k); 通过隧道; P(m); c=c-1; if(c==0) V(sd); /*P1最后一辆车通过后释放隧道 */ V(m); }
返回
2.公交车行驶问题
Semaphore s1=0, s2=0;
void Driver () { do { wait (s2); 启动开车; 正常行车; 到站停车; signal (s1); } while(TRUE); } void Conductor () { do { wait (s1); 开车门; 关车门; signal (s2); 卖票; } while(TRUE); }
单行隧道问题再分析
例:单行隧道问题。对一个单行的隧道进行模拟,为了避免 死锁,必须防止汽车同时从两端进入隧道。如果一次只允 许一辆车通过隧道,两个方向按车辆到达的先后顺序依次 通过,请用pv操作设计一个算法实现这个控制。
P1() { 通过隧道; }
P2() { 通过隧道; }
单行隧道问题再分析
分析:解决p2可以过多辆车的方法:按照读者-读者问题处理。即:p1 问题: 为读者,p2为读者,但两个读者不能同时读 。 int若 c1=c2=0,m1=m2=1,sd=1; //c1、c2为计数器,m1、m2 为互斥信 1. P1过隧道,则后续车辆可以跟进,有可能使 p2“ 饥饿” 号量 2. 若 P2过隧道,则后续车辆也可以跟进,有可能使p1“饥饿” cobegin P1() // P2() coend P1() P2() { { P(m1); P(m2); if (c1== 0 ) P(sd); if (c2== 0 ) P(sd); c1=c1+1; c2=c2+1; V(m1); V(m2); 通过隧道; 通过隧道; P(m1); P(m2); c1=c1-1; c2=c2-1; if(c1==0) V(sd); if(c2==0) V(sd); V(m1); V(m2); } }
返回
3. 和尚挑水问题
寺庙里有多个大、小和尚,一水缸。小和
尚取水,大和尚饮水。水缸容积 10 桶水,水取
自同一水井,水井每次只容一个桶取水,桶总
数3个,每次只能一个桶在水缸中入、取水。试
用 P 、 V 操作描述小和尚取水、大和尚饮水的过
程。
3. 和尚挑水问题
void shaveling() { do { 从水井打水; 往缸中放水 }while(TRUE); } void bonze() { do { 从缸中取水; 饮水; }while(TRUE); }
一方向等待的车辆进入隧道行驶。请用PV操作设计一个算
法实现这个控制。
1.单行隧道问题
例:单行隧道问题。对一个单行的隧道进行模拟,为了避免 死锁,必须防止汽车同时从两端进入隧道。如果一次只允 许一辆车通过隧道,两个方向按车辆到达的先后顺序依次 通过,请用pv操作设计一个算法实现这个控制。
P1() { 通过隧道; }
1.单行隧道问题
int countab=0,countba=0; Semaphore s=1, mutexab=1,mutexba=1; void Pab() { do { wait(mutexab);countab++; if (countab==1) then wait(s); signal(mutexab); 从A端驶入,到B端驶出; wait(mutexab); countab- -; if (countab==0) then signal(s) signal(mutexab); } while(TRUE); }
单行隧道问题再分析
假设:问题改为:一旦一辆车进入,则同一方向的车可以立即跟进,隧道最多只能过4辆 问题: 车,如何修改算法? 是p1优先或p2优先的方法。 int 1. c1=c2=0,m1=m2=1,sd=1,k1=4,k2=4 ;//c1、c2为计数器,m1、m2为互斥信号量 cobegin //k1 、 k2为控制各自方向上通过的车辆数 2. p1后续车辆可以跟进, p2 后续车辆也能跟进。 P1() // P2() 3. P1会产生“饥饿”的现象,p2也会产生“饥饿”的现象。 coend
1.单行隧道问题
分析:解决p2可以过多辆车的方法:按照读者-读者问题处理。即:p1 为读者,p2为读者,但两个读者不能同时读 。 int c1=c2=0,m1=m2=1,sd=1; //c1、c2为计数器,m1、m2、sd为互 斥信号量 cobegin P1() // P2() coend P1() P2() { { P(m1); P(m2); if (c1== 0 ) P(sd); if (c2== 0 ) P(sd); c1=c1+1; c2=c2+1; V(m1); V(m2); 通过隧道; 通过隧道; P(m1); P(m2); c1=c1-1; c2=c2-1; if(c1==0) V(sd); if(c2==0) V(sd); V(m1); V(m2); } }
mutex1=mutex2=1;分别代表可以用水井和水缸 empty=10; 水缸的容量 full=0; 水缸中的水量 count=3;水桶个数
4. 哲学家问题
对教程描述的哲学家问题,规定奇数号的哲
学家先拿起他左边的筷子,然后再去拿他右边的筷
子;而偶数号的哲学家则相反。按此规定,用P、
V操作设计一个算法实现这个控制。
进程同步与互斥习题分析
解题步骤: 1. 确定进程的个数及每个进程的工作; 2. 确定关键工作步(需要控制的); 3. 确定信号量表示的含义(开始或结束); 4. 写出伪代码。
1.单行隧道问题
对一个单行的隧道进行模拟,为了避免碰撞,必须
防止汽车同时从两端(A、B端)进入隧道。现要设计一个 自动管理系统,管理规则如下:当隧道中有车辆在行驶时 同方向的车可以驶入隧道,但另一方向的车必须在隧道外 等待;当隧道中无车时,到达 A 端(或 B 端)的车辆可以 进入隧道,但不能从A、B端同时驶入隧道;当某方向在隧 道中行驶的车辆使出了隧道且无车辆进入隧道时,应让另
P2() { 通过隧道; }
1.单行隧道问题
分析:本题涉及两个进程: P1和P2。隧道是一个临界资源 问题: ,一次只能被一辆车占有,可以把它看作互斥问题。 两个方向车辆通过隧道的交换比较平凡,系统效率不高。 设:一个互斥信号量sd=1,表示隧道是否可用。 int sd=1; cobegin P1() // P2() coend
P1() { P(sd); 通过隧道; V(sd); } } P2() { P(sd); 通过隧道; V(sd);
1.单行隧道问题
问题: 分析:为了提高效率,把问题改为:一旦一辆车进入,则同一方向的车 1. 若 P1过隧道,则后续车辆可以跟进; 可以立即跟进。写出用信号量解决此问题的代码,不考虑“饥饿”的 情况。 (按照读者-写者问题处理) 2. 若 p2过隧道,一次只能过一辆; 3个信号量:c表示计数器,m表示对临界资源计数器的控制, sd表 3.设: P1不会产生“饥饿”的现象,而 p2会产生“饥饿”的现象。
示对临界资源隧道的控制,即隧道是否可用。 int c=0,m=1,sd=1; P1() cobegin { P(m); /* m控制计数器c*/ P1() // P2() if (c== 0 ) P(sd); /*p1第一辆车通过时占有隧道*/ coend c=c+1; P2() V(m); { 通过隧道; P(m); P(sd); c=c-1; 通过隧道; if(c==0) V(sd); /*p1最后一辆车通过后释放隧道 */ V(sd); V(m); } }
1.单行隧道问题
void Pab() { do { 从A端驶入,到B端驶出; } while(E); }
void Pba () { do { 从B端驶入,到A端驶出; } while(TRUE); }
计数器:countab、countba分别表示A->B、B->A的车辆数; 信号量:s、mutexab、mutexba;
4. 哲学家问题
semaphore chopstick[5]={1,1,1,1,1}; void philosopher(int i) { do { think(); eat(); } while(true); }
4. 哲学家问题
semaphore chopstick[5]={1,1,1,1,1}; void philosopher(int i) { while(true) { think(); if(i%2 == 0) {//偶数哲学家,先右后左。 wait (chopstick[ i + 1 ] mod 5) ; wait (chopstick[ i]) ; eat(); signal (chopstick[ i + 1 ] mod 5) ; signal (chopstick[ i]) ; } else {//奇数哲学家,先左后右。 wait (chopstick[ i]) ; wait (chopstick[ i + 1 ] mod 5) ; eat(); signal (chopstick[ i]) ; signal (chopstick[ i + 1 ] mod 5) ; } }