操作系统实现生产者消费者问题_第1页
操作系统实现生产者消费者问题_第2页
操作系统实现生产者消费者问题_第3页
操作系统实现生产者消费者问题_第4页
操作系统实现生产者消费者问题_第5页
已阅读5页,还剩9页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、操作系统综合设计实现生产者消费者问题目 录第一部分:实现生产者与消费者问题一、题目21、课程设计目的22、课程设计要求2二、设计内容2三、开发环境3四、分析设计31、设计原理32、涉及的数据结构53、流程图6五、运行示例及结果分析81、运行示例82、运行结果分析:9六、个人体会9七、附录(源程序)10第一部分:实现生产者与消费者问题一、题目:实现生产者与消费者问题此问题是经典的进程同步互斥问题,问题描述参见教材第36页和第46页,要求编程实现,生产者放入产品的和消费者取走产品的速度可以调节。1、课程设计目的:在我们所学的操作系统这门课程中,关于经典进程的同步问题进行了一定的描述和探讨,介绍了几

2、个经典的算法,需要我们在实践中学会熟练运用。在生产者与消费者问题中,需要我们了解进程同步的概念,理解信号量机制的原理,掌握运用信号量解决进程同步问题的方法,进而学会运用进程的同步与互斥解决生产者与消费者的冲突问题。2、课程设计要求:生产者与消费者问题可以算作是经典进程同步问题的典型代表。该课程设计要求运用基于单缓冲区和多缓冲区的生产者与消费者问题的多种实现机制,其中利用了数据结构中的循环队列和堆栈来模拟实现是一种比较容易实现的方法。这种思想能够帮助我们更好的理解所学内容,并加以锻炼我们的动手实践能力,实现它内在具有的超强的参考价值和实践意义。该课程设计通过了解进程间的两种制约关系,从而理解信号

3、量机制;通过对实例的分析和讨论,理解信号量机制实现进程的同步及互斥的方法;通过对经典进程同步问题的剖析,初步掌握运用信号量解决进程同步问题的方法。二、设计内容在同一个进程地址空间内执行的两个线程。生产者线程生产物品,然后将物品放置在一个空缓冲区中供消费者线程消费。消费者线程从缓冲区中获得物品,然后释放缓冲区。当生产者线程生产物品时,如果没有空缓冲区可用,那么生产者线程必须等待消费者线程释放出一个空缓冲区。当消费者线程消费物品时,如果没有满的缓冲区,那么消费者线程将被阻塞,直到新的物品被生产出来,我的具体做法也是如此,建立缓冲区,生产者生产的产品放入,消费者从中取产品,如果没有产品,则等待。三、

4、开发环境此程序的设计在Windows XP操作系统下,基于Microsoft Visual C+6.00环境下的一个关于实现生产者与消费者问题的程序。用C语言实现编程。四、分析设计1、设计原理进程同步是指几个进程相互合作,一个进程到达某个点后,除非另一个进程已经完成某些操作,否则就不得不停下来,等待这些操作的结束,这就是进程同步的概念。生产者-消费者问题是一个经典的进程同步问题,该问题最早由Dijkstra提出,用以演示他提出的信号量机制。本作业要求设计在同一个进程地址空间内执行的两个线程。生产者线程生产物品,然后将物品放置在一个空缓冲区中供消费者线程消费。消费者线程从缓冲区中获得物品,然后释

5、放缓冲区。当生产者线程生产物品时,如果没有空缓冲区可用,那么生产者线程必须等待消费者线程释放出一个空缓冲区。当消费者线程消费物品时,如果没有满的缓冲区,那么消费者线程将被阻塞,直到新的物品被生产出来。生产者消费者问题是一种同步问题的抽象描述。计算机系统中的每个进程都可以消费或生产某类资源,当系统中某一进程使用某一资源时,可以看作是消耗,且该进程称为消费者。而当某个进程释放资源时,则它就相当一个生产者。 通过一个有界缓冲区把生产者和消费者联系起来。假定生产者和消费者是相互等效的,只要缓冲区未满,生产者就可以将产品送入缓冲区,类似地,只要缓冲区未空,消费者就可以从缓冲区中去走物品并消费它。生产者和

6、消费者的同步关系将禁止生产者向满的缓冲区输送产品,也禁止消费者从空的缓冲区中提取物品。 在生产者消费者问题中,信号灯具有两种功能。首先,它是跟踪资源的生产和消费的计数器;其次,它是协调资源的生产者和消费者之间的同步器。消费者通过再一指派给它的信号灯上做P操作来表示消耗资源,而生产者通过在同一信号灯上做V操作来表示生产资源。再这种信号灯的实施中,计数在每次P操作后减1,而在每次V操作中加1。个这一计数器的初始值是可利用的资源数目。当资源是不可利用时,将申请资源的进程放置在等待队列中。如果有一个资源释放,在等待队列中的第一个进程被唤醒并得到资源的控制权。 为解决这一类生产者消费者问题,设置了两个同

7、步信号灯,一个说明空缓冲区的数目,用empty表示,其初值为有界缓冲区的大小n,另一个说明缓冲区的数目,用full表示,其初制值为0。由于有界缓冲区是一个零界资源,必须互斥使用,所以另外还需设置一个互斥信号灯mutex,起初值为1。 假定在生产者和消费者之间的公用缓冲区中,具有n个缓冲区,这时可以利用互斥信号量mutex实现诸进程对缓冲池的互斥使用;利用信号量empty和full分别表示缓冲池中空缓冲区和满缓冲区的数量。又假定这些生产者和消费者互相等效果,只要缓冲池未满,生产者便可以将消息送入缓冲池;只要缓冲池未空,消费者便可以从缓冲池中取走一个消息。在生产者-消费者问题中应注意:首先,在每个

8、程序中用于互斥的wait(mutex)和signal(mutex)必须成对出现;其次,对资源信号量empty和full的wait和signal操作,同样需要成对地出现,但它们分别处于不同的程序中。生产者与消费者进程共享一个大小固定的缓冲区。其中,一个或多个生产者生产数据,并将生产的数据存入缓冲区,并有一个或多个消费者从缓冲区中取数据。假设缓冲区的大小为n(存储单元的个数),它可以被生产者和消费者循环使用。分别设置两个指针in和out,指向生产者将存放数据的存储单元和消费者将取出数据的存储单元,如图,指针in和out初始化指向缓冲区的第一个存储单元。生产者从第一个存储单元开始存放数据,一次存放一

9、条数据一条数据且in指针向后移一个位置,当in 指针指向第n个存储单元,下一次将指向第一个存储单元,如此循环反复使用缓冲区。消费者从缓冲区中逐条取走数据,一次取一条数据,相应的存储单元变为“空”,可以被生产者再次使用。每次取走一条数据,out指针向后移一个存储单元位置。试想,如果不控制生产者与消费者,将会产生什么结果? 1 2 3 4 5 6 7 8 n In out 1 2 3 4 5 6 7 8 n In out 其中,in表示存数据位置,out表示取数据位置: :被占用单元 :空存储单元图:生产者/消费者循环使用缓冲区首先,生产者和消费者可能同时进入缓冲区,甚至可能同时读/写一个存储单元

10、,将导致执行结果不确定。这显然是不允许的。所以,必须使生产者和消费者互斥进入缓冲区。即某时刻只允许一个实体(生产者或消费者)访问缓冲区,生产者互斥消费者和其他任何生产者。其次,生产者不能向满的缓冲区写数据,消费者也不能在空缓冲区中取数据,即生产者与消费者必须同步。当生产者产生出数据,需要将其存入缓冲区之前,首先检查缓冲区中是否有“空”存储单元,若缓冲区存储单元全部用完,则生产者必须阻塞等待,直到消费者取走一个存储单元的数据,唤醒它。若缓冲区内有“空”存储单元,生产者需要判断此时是否有别的生产者或消费者正在使用缓冲区,若是有,则阻塞等待,否则,获得缓冲区的使用权,将数据存入缓冲区,释放缓冲区的使

11、用权。消费者取数据之前,首先检查缓冲区中是否存在装有数据的存储单元,若缓冲区为“空”,则阻塞等待,否则,判断缓冲区是否正在被使用,若正被使用,若正被使用,则阻塞等待,否则,获得缓冲区的使用权,进入缓冲区取数据,释放缓冲区的使用权。其执行流程如图所示,伪代码如图所示。2、涉及的数据结构用资源向量Available。这是一个含有m个元素的数组,其中的每一个元素代表一类可利用的资源数目,其初始值是系统中所配置的该类全部可用资源的数目,其数值随该类资源的分配和回收而动态地改变。如果Availablej=K,则表示系统中县有RJ类资源K个。需求矩阵MAX。这是一个N*M的矩阵,它定义了系统中N个进程中的

12、每一个进程对M类资源的最大需求。如果MAXi,j=K,则表示进程I需要RJ类资源的最大数目为K。矩阵Allocation。这也是一个N*M的矩阵,它定义了系统中每一类资源当前已分配给每一进程的资源数。如果Allocationi,j=K,则表示进程i当前已分得RJ类资源的数目为K。矩阵Need。这也是一个N*M的矩阵,用以表示每一个进程尚需的各类资源数。如果Needi,j=K,则表示进程I还需要RJ类资源K个,方能完成其任务。 上述三个矩阵间存在下述关系: Needi,j=MAXi,j-Allocationi,j3、流程图等待使用权,阻塞被唤醒等待资源,阻塞数据单元加1,唤醒一个消费者归还使用权

13、存入一条数据生产一条数据是否可用存储单元 无 有是否可用 否被唤醒是否有数据单元等待资源,阻塞 有被唤醒是否可用 否消费数据空单元加1,唤醒一个生产者归还使用权被唤醒取走一条数据等待使用权,阻塞 是五、运行示例及结果分析1、运行示例:2、运行结果分析:此程序可自动输入生产者、消费者数目等条件,但程序执行过程中也进入了一种无限循环状态,若要得到较好的结果和界面需要加强编程练习。六、个人体会经过快一个月的时间来弄这个大型作业。我当时真的有点力不从心。后来老师只要我们实现OS里面的一部分功能-进程的控制和管理。就是比较有名的那两个进程算法。有于当时在实验室就对进程之间的运转有了一个全面的了解,虽然好

14、多的细节部分还不是太了解,但是对一个进程的流向和执行过程还是有个大概的认识,所以这个大型作业做起来也不是那么的简单。那些东西的详细说明在我们的教材上是没有的。后来,我就在网上和图书馆大量的找资料。先对那些算法有一个大致全面的了解。经过两个多星期的查资料。我就开始对那两个算法的代码进行完善和修改,以达到我的要求。有经过了一个多星期的调试和运行终于达到了我的要求了。并把结果截取如下。在生产者与消费者问题的算法编写程序的时候要尽可能用全所学到的函数,因为这是检测我们用C语言进行程序设计的能力的重要方式。在编写程序的时候我们不可能一次就成功,往往一个图形要修改甚至是十几次数据才能得到预期的结果。因此在

15、编写程序的时候一定不能急躁,要耐心地检测输入的数据和输出的结果,在没达到预期目的的情况下,要及时修改数据进行下一次的检测,只有这样才能成功地用C语言编写出需要的程序。 编写程序是一个长期的过程,因此不能急躁,要坐的住。由于对C语言知识已经有些遗忘,所以我找出了以前的笔记,花了半天的时间去回忆和理解。对操作系统有关消费者-生产者问题的含义也已经有点模糊,我花了一天的时间看教材,还到图书馆借阅了相关的资料,才开始编程。刚开始对如何动态实现消费者-生产者问题一筹莫展,于是和一些同学就这个问题讨论过,但是没什么好的效果。编写程序有的时候需要的就是灵感,因此当有灵感的时候就要开始做,而不能等,必须在灵感

16、未消失前付诸行动,所以才有了凌晨两点才最后做完大型作业。虽然很累,但是觉得值得。历经快一个月的时间让我马马乎乎的完成了它,从中让我得到了好多的东西,首先,这个过程锻炼了我的意志,还让我对进程的控制和编写过程有了一个更深层次的认识和理解。其次,我现在对Windows操作系统执行流程有了一个透明的认识,同时也让我对它更有亲切感。总之,这次作业让我受益匪浅!七、附录(源程序) #include #include #include typedef HANDLE Semaphore; /信号量的Windows原型 #define P(S) WaitForSingleObject(S, INFINITE)

17、 /定义Windows下的P操作 #define V(S) ReleaseSemaphore(S, 1, NULL)/定义Windows下的V操作 #define rate 1000 #define CONSUMER_NUM 4 /* 消费者个数 */ #define PRODUCER_NUM 4 /* 生产者个数 */ #define BUFFER_NUM 4 /* 缓冲区个数 */ char *thing10=s1, s2, s3, s4,; struct Buffer int productBUFFER_NUM; / 缓冲区 int start, end; / 两个指针 g_buf; S

18、emaphore g_semBuffer, g_semProduct, g_mutex; /消费者线程 DWORD WINAPI Consumer(LPVOID para) /i表示第i个消费者 Int i = *(int *)para; int ptr; /待消费的内容的指针 printf(小白兔-%03d:叶子n, i); Sleep(1800); while (1) printf(小白兔-%03d:我饿了.!n,i); /等待产品 P(g_semProduct); /有产品,先锁住缓冲区g_buf P(g_mutex); /记录消费的物品 ptr=g_buf.start; /再移动缓冲区

19、指针 g_buf.start= (g_buf.start+1)%BUFFER_NUM; /让其他消费者或生产者使用g_buf V(g_mutex); printf(小白兔-%03d:我需要buf%d = %sn, i, ptr, thingg_ductptr); Sleep(rate*rand()%10+1800); /消费完毕,并释放一个缓冲 printf(小白兔-%03d:吃绿叶buf%d = %sn,i, ptr, thingg_ductptr); V(g_semBuffer); Return 0; /生产者线程 DWORD WINAPI Producer(L

20、PVOID para) int i=*(int*)para-CONSUMER_NUM; int ptr; int data; /产品 printf(小草-%03d:小白兔快来找我!n, i); Sleep(1800); while (1) printf(小草-%03d:我爱阳光n, i); Sleep(rate*rand()%10+1800); data = rand()%10; printf(小草-%03d:我要长大!data = %s!n, i, thingdata); /等待存放空间 P(g_semBuffer); /有地方,先锁住缓冲区g_buf P(g_mutex); /记录消费的物

21、品 ptr = g_buf.end; /再移动缓冲区指针 g_buf.end = (g_buf.end+1)%BUFFER_NUM; /让其他消费者或生产者使用 g_buf V(g_mutex); printf(小草-%03d:长大了!buf%d = %sn, i, ptr, thingdata); g_ductptr = data; Sleep(rate/2*rand()%10+1800); /放好了完毕,释放一个产品 printf(小草-%03d: buf%d=%s 小白兔快来!n,i, ptr,thingg_ductptr); V(g_semProduct);

22、 return 0; int main(int argc, char *argv) /线程技术,前面为消费者线程,后面为生产者线程 HANDLE hThreadCONSUMER_NUM+PRODUCER_NUM; /线程计数 /srand(time(); DWORD tid; int i=0; /初始化信号量 g_mutex=CreateSemaphore(NULL,BUFFER_NUM,BUFFER_NUM,mutexOfConsumerAndProducer); g_semBuffer=CreateSemaphore(NULL,BUFFER_NUM,BUFFER_NUM,BufferSemaphone); g_semProduct= CreateSemaphore(NULL, 0, BUFFER_NUM, Prod

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论