操作系统原理之经典PV问题

本文记录9道PV问题的解,不保证正确,仅供参考,,

1、 有一个仓库,可以存放 A 和 B 两种产品,仓库的存储空间足够大,但要求:
( 1)一次只能存入一种产品( A 或 B);
( 2) -N < (A 产品数量-B 产品数量) < M。
其中, N 和 M 是正整数。试用“存放 A”和“存放 B”以及 P、 V 操作描述产品 A 与
产品 B 的入库过程。

 1 Semaphore mutex = 1;   //互斥信号量
 2 Semaphore a = M-1 ;   //存放A的资源信号量,初值为M-1
 3 Semaphore b = N-1;      //存放B的资源信号量,初值为N-1
 4 存放 A:
 5 {
 6 while(true)
 7 {
 8         Get A;
 9         P(&a);
10          P(&mutex);
11 Put A;
12 V(&mutex);
13 V(&b);
14 }
15 }
16 存放B:
17 {
18 while(true)
19 {
20         Get B;
21         P(&b);
22         P(&mutex);
23         Put B;
24         V(&mutex);
25         V(&a);
26 }
27 }

2、 桌子上有一只盘子,最多可容纳两个水果,每次只能放入或取出一个水果。爸爸专向盘
子放苹果( apple),妈妈专向盘子中放桔子( orange);两个儿子专等吃盘子中的桔子,
两个女儿专等吃盘子中的苹果。请用 P、 V 操作来实现爸爸、妈妈、儿子、女儿之间的
同步与互斥关系。

 1 Semaphore mutex = 1;      //互斥信号量, 其初值为1
 2 Semaphore empty = 2;       //记录允许向盘子中放入水果的个数,初值为2
 3 Semaphore orange = 0;      //盘子中已放入的苹果的个数,初值为0
 4 Semaphore apple = 0;      //盘子中已放入的桔子的个数,初值为0
 5 main()
 6 {
 7 Cobegin
 8 {
 9   father                    //父亲进程
10     {
11     while (true)
12        {
13            P(empty);           //减少盘中可放入的水果数
14                 P(mutex);           //申请向盘中取、放水果
15                 向盘中放苹果;
16                 V(mutex);           //允许向盘中取、放水果
17                 V(apple);           //递增盘中的苹果数
18         }
19      }
20     mother                    //母亲进程
21     {
22     while (true)
23        {
24           P(empty);           //减少盘中可放入的水果数
25                 P(mutex);           //申请向盘中取、放水果
26                 向盘中放桔子;
27                 V(mutex);           //允许向盘中取、放水果
28                 V(orange);          //递增盘中的桔子数
29         }
30     }
31     daughteri(i=1,2)      //两女儿进程
32     {
33     while (true)
34        {
35             P(apple);           //减少盘中苹果数
36                 P(mutex);           //申请向盘中取、放水果
37                 取盘中苹果;
38                 V(mutex);           //允许向盘中取、放水果
39                 V(empty);           //递增盘中可放入的水果数
40         }
41      }
42     sonj(j=1,2)           //两儿子进程
43     {
44     while (true)
45        {
46           P(orange);          //减少盘中桔子数
47                 P(mutex);           //申请向盘中取、放水果
48                 取盘中桔子;
49                 V(mutex);           //允许向盘中取、放水果
50                 V(empty);           //递增盘中可放入的水果数
51         }
52      }
53    }
54     Coend
55 }  

3、 有一个理发师,一把理发椅和 N 把供等候理发的顾客坐的椅子。如果没有顾客,则理发
师便在理发师椅子上睡觉;当一个顾客到来时,必须唤醒理发师进行理发;如果理发师
正在理发时又有顾客来到,则如果有空椅子可坐,他就坐下来等,如果没有空椅子,他
就离开。为理发师和顾客各编一段程序(伪代码)描述他们的行为,要求不能带有竞争
条件。

 1 Semaphore mutex = 1;    //互斥信号量,初值为1.
 2 Semaphore  Wait = 0;     //等待服务的顾客数
 3 Semaphore  barbers= 0;    //等待顾客的理发师数
 4 Int custNum = 0;    //等待的顾客(还没理发的)
 5
 6 Costumer()
 7 {
 8   while(true)
 9   {
10         P(mutex);            //申请理发
11         if(custNum>0)
12      {
13             if(custNum<N)   //若等待人数小于N
14        {
15                 V(mutex);     //释放进程等待
16                 CustNum++;     //增加等待人数
17             }
18        else            //若等待人数超过N
19         {
20                 V(mutex);   //释放进程等待
21                 离开;
22              }
23      }
24     else                //若目前无人等待
25     {
26             V(mutex);        //释放进程等待
27             V(barbers);     //如果必要的话,唤醒理发师
28             理发;
29             离开;
30             P(mutex);        //要求进程等待
31             custNum--;        //顾客人数减1
32             V(mutex);       //释放进程等待
33             V(wait);        //等待人数减1
34     }
35   }
36 }
37
38 Barber()
39 {
40   while(true)
41   {
42         P(mutex);            //要求进程等待
43         if(custNum ==0)    //目前无顾客
44      {
45             V(mutex);        //释放进程等待
46             P(barbers);        //理发师睡觉
47        }
48     else
49     {
50             V(mutex);        //释放进程等待
51             理发;
52     }
53   }
54 }

4、 吸烟者问题。三个吸烟者在一间房间内,还有一个香烟供应者。为了制造并抽掉香烟,
每个吸烟者需要三样东西:烟草、纸和火柴。供应者有丰富的货物提供。三个吸烟者中,
第一个有自己的烟草,第二个有自己的纸,第三个有自己的火柴。供应者将两样东西放
在桌子上,允许一个吸烟者进行对健康不利的吸烟。当吸烟者完成吸烟后唤醒供应者,
供应者再放两样东西(随机地)在桌面上,然后唤醒另一个吸烟者。试为吸烟者和供应
者编写程序解决问题。

 1 Semaphore S = 1;                //供应者
 2 Semaphore S1,S2,S3;                //三个吸烟者
 3 S1 = S2 = S3 = 0;
 4 bool flag1,flag2,fiag3;            //三种吸烟原料
 5 fiag1=flag2=flag3=true;
 6
 7 Apply()                            //供应者
 8 {
 9   While(true)
10   {
11           P(S);
12         取两样香烟原料放桌上,由flagi标记;
13         if (flag2 && flag3) //供纸和火柴
14       {
15            V(S1);          //唤醒吸烟者一
16           }
17          else if(flag1 && fiag3) //供烟草和火柴
18       {
19            V(S2);                //唤醒吸烟者二
20           }
21        else                      //供烟草和纸
22       {
23            V(S3);                //唤醒吸烟者三
24            }
25    }
26 }
27
28 Smoker1()                         //吸烟者一
29 {
30    While(true)
31    {
32        P(S1);
33        取原料;
34        做香烟;
35        V(S);                    //唤醒供应者
36        吸香烟;
37    }
38 }
39
40 smoker2()                        //吸烟者二
41 {
42    While(true)
43    {
44        P(S2);
45        取原料;
46        做香烟;
47        V(S);                    //唤醒供应者
48        吸香烟;
49    }
50 }  
51
52 Smoker3()                        //吸烟者三
53 {
54    While(true)
55 {
56        P(S3);
57        取原料;
58        做香烟;
59        V(S);                    //唤醒供应者
60       吸香烟;
61    }
62 }

5、 面包师问题。面包师有很多面包和蛋糕,由 n 个销售人员销售。每个顾客进店后先取
一个号,并且等着叫号。当一个销售人员空闲下来,就叫下一个号。请分别编写销售人
员和顾客进程的程序。

 1 Semaphore buyer= 0;                //顾客人数
 2 Semaphore seller = n;            //销售人员数
 3 Semaphore mutex_s = 1;            //用于销售人员的互斥信号量
 4 Semaphore mutex_b = 1;            //用于顾客的互斥信号量
 5 int count_s = 0;                //记录取号的值
 6 int count_b = 0;                //记录叫号的值
 7
 8 void Buy()                    //顾客进程
 9 {
10      进店;
11     P(mutex_b);          //取号
12     count_b++;
13    V(mutex_b);
14    V(buyer);
15    P(seller);            //等待叫号
16     买面包;
17     离开
18 }
19
20 void Sell()
21 {
22     while(true)
23     {
24          P(buyer);
25          P(mutex_s);   //叫号
26          count_s++;
27          叫编号为count_s的顾客;
28          V(mutex_s);
29          V(seller);
30     }
31 }

6、 桌上有一空盘,运行存放一只水果,爸爸可向盘中放苹果,也可放桔子,儿子专等吃盘
中的桔子,女儿专等吃盘中的苹果。规定当盘中空时一次只能放一个水果供吃者取用,
用 P,V 原语实现爸爸儿子和女儿 3 个并发进程的同步。

 1 Semaphore S = 1;      //S 表示盘子是否为空;
 2 Semaphore Sa = 0;        //Sa 表示盘中是否有苹果;
 3 Semaphore Sb = 0;    //Sb 表示盘中是否有桔子;
 4
 5 Father()            //父亲进程
 6 {
 7     while(TRUE)
 8   {
 9         P(S);
10         将水果放入盘中;
11         if (放入的是桔子)
12             V(Sb);
13         else
14             V(Sa);
15     }
16 }
17
18 Son()                  //儿子进程
19 {
20     while(TRUE)
21   {
22         P(Sb);
23         从盘中取出桔子;
24         V(S);
25      吃桔子;
26     }
27 }
28
29 Daughter()            //女儿进程
30 {
31     while(TRUE)
32   {
33         P(Sa);
34         从盘中取出苹果;
35         V(S);
36         吃苹果;
37     }
38 }

7、 写者优先的读者--写者问题。读者-写者问题为数据库访问建立了一个模型。例如,一
个系统,其中有许多竞争的进程试图读写其中的数据,多个进程同时读是可以接受的,但如
果一个进程正在更新数据库,则所有的其他进程都不能访问数据库,即使读操作也不行。
写者优先是指当一个写者到达时,将阻止其后面的读者进入数据库,直到其离开为止。

 1 Semaphore Mut1, Mut2, Wmutex, Fmutex;          //互斥信号量
 2 int Rcount, Wcount;                          //读写者人数
 3 Mut1 = Mut2 = WMutex = Fmutex = 1;
 4 Rcount = Wcount = 0;
 5
 6 Writer()                            //写者进程
 7 {
 8    While(true)
 9    {
10        P(Mut1);
11        Wcount=Wcount+1;
12        If (Wcount==1)
13      {
14            P(Fmutex);     //如有读者,写者阻塞在此处
15        }
16        V(Mut1);
17        P(WMutex);
18        写;
19        V(Wmutex);
20        P(Mut1);
21        Wcount=Wcount-1;
22        If (Wcount==0)
23       {
24            V(Fmutex);
25        }
26        V(Mut1);
27    }
28 }
29
30 Reader()                            //读者进程
31 {
32    While(true)
33    {
34        P(Mut2);
35        Rcount=Rcount+1;
36        If (Rcount==1)
37       {
38            P(Fmutex);
39        }
40        V(Mut2);
41        读;
42        P(Mut2);
43        Rcount=Rcount-1;
44        If (Rcount==0)
45       {
46             V(Fmutex);
47        }
48        V(Mut2);
49    }
50 } 

8、 在天津大学与南开大学之间有一条弯曲的小路,这条路上每次每个方向上只允许一辆自
行车通过。但其中有一个小的安全岛 M,同时允许两辆自行车停留,可供两辆自行车已
从两端进入小路的情况下错车使用。如图所示。


下面的算法可以使来往的自行车均可顺利通过。其中使用了 4 个信号量, T 代表天大路
口资源, S 代表南开路口资源, L 代表从天大到安全岛一段路的资源, K 代表从南开到
安全岛一段路的资源。程序如下,请在空白位置处填写适当的 PV 操作语句,每处空白
可能包含若干个 PV 操作语句。

 1 begin
 2     t:=1;s:=1;l:=1;k:=1;
 3     cobegin
 4     从天大到南开的进程
 5         begin
 6             ______(1)______
 7            通过 L 路段;
 8            进入安全岛 M;
 9            ______(2)______
10            通过 K 路段
11            ______(3)______
12         end
13    从南开到天大的进程
14        begin
15           略,与“从天大到南开的进程”相反。
16        end
17     coend
18 end              

解答:

(1) P(t); P(l);

(2) V(l); P(k);

(3) V(k); V(t);

9、 三个进程 P1、 P2、 P3 互斥使用一个包含 N(N>0)个单元的缓冲区。 P1 每次用 produce()
生成一个正整数并用 put()送入缓冲区某一空单元中;P2 每次用 getodd()从该缓冲区中
取出一个奇数并用 countodd()统计奇数个数;P3 每次用 geteven()从该缓冲区中取出一
个偶数并用 counteven()统计偶数个数。请用信号量机制实现这三个进程的同步与互斥活
动,并说明所定义信号量的含义。要求用伪代码描述。

 1 P1()
 2 {
 3    While(true)
 4    {
 5        X = produce();      //生成一个数
 6       P(empty);     //是否有空单元格
 7        P(mutex);    //进入临界区
 8        Put();
 9        if(X%2 == 0)
10             V(s2);   //如果是偶数,向P3发出信号
11        else
12              V(s1);   //如果是奇数,向P2发出信号
13        V(mutex);         //离开临界区,释放互斥信号量
14    }
15 }
16
17 P2()
18 {
19    While(true)
20    {
21        P(s1);     //收到P1发送来的信号,已产生奇数
22       P(mutex);         //进入临界区
23        getodd();
24        countodd():=countodd()+1;
25        V(mutex);
26        V(empty);         //离开临界区,释放互斥信号量
27    }
28 }
29
30 P3()
31 {
32    While(true)
33    {
34       P(s2)        //收到P1发送来的信号,已产生偶数
35       P(mutex);         //进入临界区
36       geteven();
37       counteven():=counteven()+1;
38       V(mutex);
39       V(empty);         //离开临界区,释放互斥信号量
40    }
41 }
时间: 2024-10-09 00:26:50

操作系统原理之经典PV问题的相关文章

【转载】深入研究Windows内部原理绝对经典的资料

原文:深入研究Windows内部原理绝对经典的资料 另一篇资料:深入研究Windows内部原理系列 (为了方便大家下,我打包了放在一下地址: 1-6:http://download.csdn.net/detail/wangqiulin123456/4601530 7-12:http://download.csdn.net/detail/wangqiulin123456/4601508 13-16:http://download.csdn.net/detail/wangqiulin123456/4

编译原理三大经典书籍

1.龙书(Dragon book)英文名:Compilers: Principles,Techniques,and Tools作者:Alfred V.Aho,Ravi Sethi,Jeffrey D.Ullman中文名:编译原理技术和工具 2.虎书(Tiger book)英文名:Modern Compiler Implementation in C作者:Andrew W.Appel,with Jens Palsberg中文名:现代编译原理-C语言描述 3.鲸书(Whale book)英文名:Ad

马哥学习笔记三十二——计算机及操作系统原理

缓存方式: 直接映射 N路关联 缓存策略: write through:通写 write back:回写 进程类别: 交互式进程(IO密集型) 批处理进程(CPU密集型) 实时进程(Real-time) CPU: 时间片长,优先级低IO:时间片短,优先级高 Linux优先级:priority 实时优先级: 1-99,数字越小,优先级越低 静态优先级:100-139,数据越小,优先级越高 实时优先级比静态优先级高 nice值:调整静态优先级   -20,19:100,139   0:120 ps

漫谈怎样学习操作系统原理

本人学习计算机技术至今,对于怎样学习操作系统原理有一点自己的看法,如今写出来,希望对大家能有所助! 操作系统怎么学.首先要想操作系统是怎么来的,在没有操作系统的年代里,人们是怎么编程的. 这是首要的问 题.不知道有没有人看过INTEL官方的CPU文档,总是分为应用级编程.系统级编程.指令集这三块.当中系统级编 程这一块最复杂,我不说内容,就单从文件的大小来看,IA-64编程手冊的应用级编程卷是2MB,系统卷却有6MB.就 连IA-32编程手冊上的系统卷部分也远比应用卷的要多.当然这些内容我还没有

第五十二课 linux操作系统原理、虚拟机基础原理

linux操作系统原理 linux操作系统原理 虚拟机技术基础原理 虚拟机技术基础原理

漫谈如何学习操作系统原理

本人学习计算机技术至今,对于如何学习操作系统原理有一点自己的看法,现在写出来,希望对大家能有所助! 操作系统怎么学,首先要想操作系统是怎么来的,在没有操作系统的年代里,人们是怎么编程的.这是首要的问 题.不知道有没有人看过INTEL官方的CPU文档,总是分为应用级编程.系统级编程.指令集这三块.其中系统级编 程这一块最复杂,我不说内容,就单从文件的大小来看,IA-64编程手册的应用级编程卷是2MB,系统卷却有6MB.就 连IA-32编程手册上的系统卷部分也远比应用卷的要多.当然这些内容我还没有看

操作系统原理2——OS结构

操作系统原理2——OS结构 计算机系统是由硬件系统和软件系统两部分组成, 操作系统是软件系统的一个组成部分,它是直接在硬件系统的基础上工作的,所以在研究操作系统之前,先必须对计算机系统的结构有一个基本的了解,本章就是讲述计算机系统结构的基本知识. 本章的考核 知识点 是: 1.计算机系统的层次结构 2.硬件环境 3.操作系统结构 学习本章要求:了解计算机系统的结构,有关硬件的I/O中断和存储结构,硬件的保护措施:有关操作系统的结构,操作系统提供的使用接口. 重点 是:硬件环境和操作系统的结构 一

操作系统原理(转)

操作系统原理   我们每天都同操作系统打交道,了解一些操作系统原理上的知识是绝对有必要的,它可以让你了解操作系统内部是怎么工作的,为什么会出现这样那样的问题,为我们解决这些问题提供思路. 本文完全是为普通电脑用户写的,省略了所有难以理解的算法.原理,没有太多细节上的东西,只是针对普通电脑用户可能感兴趣的问题给出了实现思想.写这些东 西只是我的一相情愿,就怕我还是写得深了些,初学者读不懂.如果这10K文字能让你对操作系统有更深的了解,那也就不枉了这几个汗流浃背的夏日午后了. Q:什么是中断?A:中

操作系统原理(二),进程、线程

Technorati 标签: 操作系统,原理 现代操作系统比如,Linux,Windows等,都是支持"多任务"的操作系统.所谓多任务,指的就是操作系统可以同时运行多个任务.也就是在同一台电脑上,可以同时上网.听歌.使用Word,在过去单核的CPU上都已经可以支持多任务,实现的方式是操作系统让各个任务轮流交替执行.,比如任务1执行0.01秒,切换到任务2,任务2执行0.01秒,再切换到任务3,执行0.01秒,因为CPU执行速度非常块,我们感觉到所有任务都是并发处理. 到了多核CPU时代