生产者-消费者实验1.1 实验目的和规定1.1.1 实验目的操作系统的基本控制和管理控制都环绕着进程展开,其中的复杂性是由于支持并发和并发机制而引起的自从操作系统中引入并发程序设计后,程序的执行不再是顺序的,一种程序未执行完而另一种程序便已开始执行,程序外部的顺序特性消失,程序与计算不再一一相应并发进程也许是无关的,也也许是交互的然而,交互的进程共享某些变量,一种进程的执行也许会影响其她进程的执行成果,交互的并发进程之间具有制约关系、同步关系其中典型模型便是生产者-消费者模型本实验通过编写和调试生产者-消费者模拟程序,进一步结识进程并发执行的实质,加深对进程竞争关系,协作关系的理解,掌握使用信号量机制与P、V操作来实现进程的同步与互斥1.1.2 实验规定1.用高档语言编写一种程序,模拟多种生产者进程和多种消费者进程并发执行,并采用信号量机制与P、V操作实现进程间同步与互斥2.撰写实验报告,报告应涉及如下内容:(1) 实验目的;(2) 实验内容;(3) 设计思路;(4) 程序流程图;(5) 程序中重要数据构造和函数阐明;(6) 带注释的源程序代码;(7) 程序运营成果及分析;(8) 实验收获与体会。
1.2 预备知识1.2.1 生产者—消费者问题生产者—消费者问题表述如下:如图3.1所示,有n个生产者和m个消费者,连接在具有k个单位缓冲区的有界环状缓冲上,故又称有界缓冲问题生产者不断生成产品,只要缓冲区未满,生产者进程pi所生产的产品就可投入缓冲区;类似的,只要缓冲区非空,消费者进程cj就可以从缓冲区取走并消耗产品图 3.1 生产者—消费者问题示意图出名的生产者—消费者问题(producer-consumer problem)是计算机操作系统中并发进程内在关系的一种抽象,是典型的进程同步问题在操作系统中,生产者进程可以是计算进程、发送进程,而消费者进程可以是打印进程、接受进程等,解决好生产者—消费者问题就解决了一类并发进程的同步问题操作系统实现进程同步的机制称为同步机制,它一般由同步原语构成不同的同步机制采用不同的同步措施,迄今已设计出多种同步机制,本实验采用最常用的同步机制:信号量及PV操作1.2.2 信号量与PV操作1965年,荷兰计算机科学家E.W.Dijkstra提出新的同步工具——信号量和PV操作,她将交通管制中多种颜色的信号灯管理措施引入操作系统,让多种进程通过特殊变量展开交互。
一种进程在某一核心点上被迫停止直至接受到相应的特殊变量值,通过这一措施任何复杂的进程交互规定均可得到满足,这种特殊变量就是信号量(semaphore)为了通过信号量传送信号,进程可运用P和V两个特殊操作来发送和接受信号,如果协作进程的相应信号仍未达到,则进程被挂起直至信号达到为止在操作系统中用信号量表达物理资源的实体,它是一种与队列有关的整型变量具体实现时,信号量是一种变量类型,用一种记录型数据构造表达,有两个分量:一种是信号量的值,另一种是信号量队列的指针信号量在操作系统中重要用于封锁临界区、进程同步及维护资源计数除了赋初值之外,信号量仅能由同步原语PV对其操作,不存在其她措施可以检查或操作信号量,PV操作的不可分割性保证执行的原子性及信号量值的完整性运用信号量和PV操作即可解决并发进程竞争问题,又可解决并发进程协作问题信号量按其用途可分为两种:公用信号量,联系一组并发进程,有关进程均可在此信号量上执行PV操作,用于实现进程互斥;私有信号量,联系一组并发进程,仅容许此信号量所拥有的进程执行P操作,而其她有关进程可在其上执行V操作,初值往往为0或正整数,多用于并发进程同步信号量的定义为如下数据构造:typedef struct semaphore { int value; //信号量的值 struct pcb *list; //信号量队列的指针 }信号量阐明: semaphore s;P、V操作原语描述如下:(1) P(s):s.value--;若s.value≥0,则执行P(s)的进程继续执行;若s.value<0,则执行P(s)的进程被阻塞,并把它插入到等待信号量s的阻塞队列中。
2) V(s):s.value++;若s.value≤0,则执行V(s)的进程从等待信号量s的阻塞队列中唤醒头一种进程,然后自己继续执行若s.value>0 ,则执行V(s)的进程继续执行; 1.2.3 信号量实现互斥信号量和PV操作可用来解决进程互斥问题为使多种进程能互斥地访问某临界资源,只需为该资源设立一互斥信号量mutex,并置初值为1,然后将各进程访问该资源的临界区置于P(mutex)和V(mutex)操作之间即可用信号量和PV操作管理并发进程互斥进入临界区的一般形式为:semaphore mutex;mutex = 1;cobeginprocess Pi() /*i = 1,2, …,n */{ P(mutex); /*临界区*/ V(mutex); }coend当有进程在临界区中时,mutex的值为0或负值,否则mutex值为1,由于只有一种进程,可用P操作把mutex减至0,故可保证互斥操作,这时试图进入临界区的其他进程会因执行P(mutex)而被迫等待mutex的取值范畴是1~-(n-1),表白有一种进程在临界区内执行,最多有n-1个进程在信号量队列中档待。
1.2.4 信号量解决生产者—消费者问题信号量和PV操作不仅可以解决进程互斥问题,并且是实现进程同步的有力工具在协作进程之间,一种进程的执行依赖于协作进程的信息或消息,在尚未得到来自协作进程的信号或消息时等待,直至信号或消息达到时才被唤醒生产者—消费者问题是典型的进程同步问题,对于生产者进程:生产一种产品,当要送入缓冲区时,要检查与否有空缓冲区,若有,则可将产品送入缓冲区,并告知消费者进程;否则,等待;对于消费者进程:当它去取产品时,要看缓冲区中与否有产品可取,若有则取走一种产品,并告知生产者进程,否则,等待这种互相等待,并互通信息就是典型的进程同步因此应当设两个同步信号量:信号量empty表达可用的空缓冲区的数目,初值为k;信号量full表达可以使用产品的数目,初值为0缓冲区是一种临界资源,必须互斥使用,因此此外还需要设立一种互斥信号量mutex,其初值为1用信号量机制解决生产者—消费者问题可描述如下:item B[k];semaphore empty; empty=k; //可以使用的空缓冲区数semaphore full; full=0; //缓冲区内可以使用的产品数semaphore mutex; mutex=1; //互斥信号量int in=0; //放入缓冲区指针int out=0; //取出缓冲区指针 cobeginprocess producer_i() process consumer(){ {While(true) While(true) { { produce(); P(full);P(empty); P(mutex);P(mutex); take from B[out];append to B[in]; out = (out+1)%k;in = (in+1)%k; V(mutex);V(mutex); V(empty);V(full); consume();} } } } Coend程序中的P(mutex)和V(mutex)必须成对浮现,夹在两者之间的代码段是临界区;施加于信号量empty和full上的PV操作也必须成对浮现,但分别位于不同的程序中。
在生产者消费者问题中,P操作的顺序是很重要的,如果把生产者进程中的两个P操作互换顺序,那么,当缓冲区中存满k件产品时,生产者又生产一件产品,在它欲向缓冲区寄存时,将在P(empty)上等待,由于此时mutex=0,它已经占有缓冲区,这时消费者预取产品时将停留在P(mutex)上而得不到使用缓冲区的权力这就导致生产者等待消费者取走产品,而消费者却在等待生产者释放缓冲区的占有权,这种互相之间的等待永远不也许结束因此,在使用信号量和PV操作实现进程同步时,特别要当心P操作的顺序,而V操作的顺序无关紧要一般来说,用于互斥的信号量上的P操作总是在背面执行1.3 生产者消费者问题模拟实现1.3.1 实验内容考虑一种系统中有n个进程,其中部分进程为生产者进程,部分进程为消费者进程,共享具有k个单位的缓冲区现规定用高档语言编写一种程序,模拟多种生产者进程和多种消费者进程并发执行的过程,并采用信号量机制与P、V操作实现生产者进程和消费者进程间同步以及对缓冲区的互斥访问运用信号量机制解决此问题的算法见3.2.4所示1.3.2 实验指引1. 设计提示(1)本实验并不需要真正创立生产者和消费者进程,每个进程用一种进程控制块(PCB)表达。
PCB数据构造如下:typedef struct Process//进程PCB { char name[10]; //进程名 int roleFlag; //进程类型(1:生产者 0: 消费者) int currentState; //进程状态(1: 可运营态 0: 阻塞态) int currentStep; //断点 int data; //临时数据 int code; //进程编号}Process;(2)程序中应指定缓冲区的数目,进程总个数等,现考虑共有4个生产者和消费者进程,缓冲区数目是两个,定义如下所示:#define dataBufferSize 2 //缓冲区数目#define processNum 4 //进程数量(生产者、消费者进程总数目)struct DataBuffer //缓冲区{ int buffer[dataBufferSize]; int count; //目前产品数量} dataBuffer;(3)为解决生产者-消费者问题需设两个同步信号量:信号量empty表达可用的空缓冲区的数目,初值为缓冲区数目;信号量full表达可以使用产品的数目,初值为0。
缓冲区是一种临界资源,必须互斥使用,因此此外还需要设立一种互斥信号量mutex,其初值为1信号量定义和阐明如下所示:typedef struct Seamphore //信号量{ int value; //信号量的值 int *pcq; //信号量队列指针} Seamphore;int producerCongestionQueue[processNum]; //等。