生产者消费者问题-------操作系统课程设计

整理文档很辛苦,赏杯茶钱您下走!

免费阅读已结束,点击下载阅读编辑剩下 ...

阅读已结束,您可以下载文档离线阅读编辑

资源描述

课程设计报告课程名称:操作系统专业计算机科学与技术学生姓名班级学号指导教师完成日期信息工程学院1题目:生产者-消费者问题的模拟实现一、设计目的本课程设计是学习完“操作系统原理”课程后进行的一次全面的综合训练,通过课程设计,更好地掌握操作系统的原理及实现方法,加深对操作系统基础理论和重要算法的理解,加强学生的动手能力。二、设计内容(1)概述设计目的:通过研究Linux的进程机制和信号量实现生产者消费者问题的并发控制。说明:有界缓冲区内设有20个存储单元,放入/取出的数据项设定为1-20这20个整型数。设计要求:(1)每个生产者和消费者对有界缓冲区进行操作后,即时显示有界缓冲区的全部内容,当前指针位置和生产者/消费者县城的标识符。(2)生产者和消费者各有两个以上。(3)多个生产者或多个消费者之间须有共享对缓冲区进行操作的函数代码。(2)设计原理通过一个有界缓冲区把生产者和消费者联系起来。假定生产者和消费者的优先级是相同的,只要缓冲区未满,生产者就可以生产产品并将产品送入缓冲区。类似地,只要缓冲区未空,消费者就可以从缓冲区中取走产品。应该禁止生产者向满的缓冲区送入产品,同时也应该禁止消费者从空的缓冲区中取出产品,这一机制有生产者线程和消费者线程之间的互斥关系来实现。与计算打印两进程同步关系相同,生产者和消费者两进程P和C之间应满足下列两个同步条件:①只有在缓冲池中至少有一个缓冲区已存入消息后,消费者才能从中提取信息,否则消费者必须等待。②只有缓冲池中至少有一个缓冲区是空时,生产者才能把消息放入缓冲区,否则生产者必须等待。为了满足第一个同步条件,设置一个同步信号量full,它代表的资源是缓冲区满,它的初始值为0,它的值为n时整个缓冲池满。这个资源是消费者类进程C所有,C进2程可以申请该资源,对它施加P操作,而C进程的合作进程生产者进程P对它施加V操作。同样为了满足第二个同步条件,设置另一个同步信号量empty,它代表的资源是缓冲空区,它的初始值为n,表示缓冲池中所有缓冲区空。信号量full表示可用缓冲区数量,信号量empty表示缓冲区数量,设置整型变量:存入指针in和取出指针out。为解决生产者/消费者问题,应该设置两个资源信号量,其中一个表示空缓冲区的数目,用g_hFullSemaphore表示,其初始值为有界缓冲区的大小SIZE_OF_BUFFER;另一个表示缓冲区中产品的数目,用g_hEmptySemaphore表示,其初始值为0.另外,由于有界缓冲区是一个临界资源,必须互斥使用,所以还需要在设置一个互斥信号量g_hMutex,初始值为1.P原语的主要动作是:①sem减1;②若sem减一后仍大于或等于零,则进程继续执行;③若sem减一后小于零,则该进程被阻塞后入与该信号相对应的队列中,然后转进程调度。V原语的操作主要动作是:①sem加1;②若相加结果大于零,进程继续执行;③若相加结果小于或等于零,则从该信号的等待队列中唤醒一等待进程然后再返回原进程继续执行或转进程调度。采用的同步方法:1)利用函数CreateMutex(NULL,FALSE,NULL)创建互斥信号量g_hMutex,表示缓冲区当前的状态,若为true时,则表示缓冲区正被别的进程使用。三个参数表示的意义分别为:指向安全属性的指针,初始化互斥对象的所有者,指向互斥对象名的指针。2)利用函数CreateSemaphore(NULL,SIZE_OF_BUFFER-1,SIZE_OF_BUFFER-1,NULL)创建缓冲区满的信号量g_hFullSemaphore,值为true时表示缓冲区已满。四个参数分别为:表示是否允许继承、设置信号机的初始计数、设置信号机的最大计数、指定信号机对象的名称(-1是因为计数从开始)。33)利用函数CreateSemaphore(NULL,0,SIZE_OF_BUFFER-1,NULL)创建缓冲区空的信号量g_hEmptySemaphore,该值为true时表示缓冲区为空。5、数据定义及其详细解释constunsignedshortSIZE_OF_BUFFER=20;//缓冲区长度unsignedshortProductID=0;//产品号unsignedshortConsumeID=0;//将被消耗的产品号unsignedshortin=0;//产品进缓冲区时的缓冲区下标unsignedshortout=0;//产品出缓冲区时的缓冲区下标intg_buffer[SIZE_OF_BUFFER];//缓冲区是个循环队列boolg_continue=true;//使程序跳出循环,控制程序结束HANDLEg_hMutex;//用于线程间的互斥HANDLEg_hFullSemaphore;//当缓冲区满时迫使生产者等待HANDLEg_hEmptySemaphore;//当缓冲区空时迫使消费者等待DWORDWINAPIProducer(LPVOID);//生产者线程DWORDWINAPIConsumer(LPVOID);//消费者线程(3)详细设计及编码流程图生产者:sem=sem-1入口s=0调用进程入等待队列转进程调度返回是否4消费者:程序清单1.存储结构定义利用信号量解决生产者消费者问题constunsignedshortSIZE_OF_BUFFER=10;//缓冲区长度unsignedshortProductID=0;//产品号unsignedshortConsumeID=0;//将被消耗的产品号unsignedshortin=0;//产品进缓冲区时的缓冲区下标unsignedshortout=0;//产品出缓冲区时的缓冲区下标intg_buffer[SIZE_OF_BUFFER];//缓冲区是个循环队列boolg_continue=true;//控制程序结束HANDLEg_hMutex;//用于线程间的互斥HANDLEg_hFullSemaphore;//当缓冲区满时迫使生产者等待HANDLEg_hEmptySemaphore;//当缓冲区空时迫使消费者等待DWORDWINAPIProducer(LPVOID);//生产者线程DWORDWINAPIConsumer(LPVOID);//消费者线程2.算法相关的函数(1)创建各个互斥信号以及生产者线程和消费者线程的函数在如下主函数里面所示:intmain(){入口sem=sem-1sem=sem-1S=0唤醒等待队列中的一个进程式返回或转进程调度返回否是5//创建各个互斥信号g_hMutex=CreateMutex(NULL,FALSE,NULL);g_hFullSemaphoreCreateSemaphore(NULL,SIZE_OF_BUFFER-1,SIZE_OF_BUFFER-1,NULL);g_hEmptySemaphore=CreateSemaphore(NULL,0,SIZE_OF_BUFFER-1,NULL);//调整下面的数值,可以发现,当生产者个数多于消费者个数时,//生产速度快,生产者经常等待消费者;反之,消费者经常等待。constunsignedshortPRODUCERS_COUNT=3;//生产者的个数constunsignedshortCONSUMERS_COUNT=1;//消费者的个数//总的线程数constunsignedshortTHREADS_COUNTPRODUCERS_COUNT+CONSUMERS_COUNT;HANDLEhThreads[PRODUCERS_COUNT];//各线程的handleDWORDproducerID[CONSUMERS_COUNT];//生产者线程的标识符DWORDconsumerID[THREADS_COUNT];//消费者线程的标识符//创建生产者线程for(inti=0;i{hThreads[i]=CreateThread(NULL,0,Producer,NULL,0,&producerID[i]);if(hThreads[i]==NULL)return-1;}//创建消费者线程for(i=0;i{hThreads[PRODUCERS_COUNT+i]=CreateThread(NULL,0,Consumer,NULL,0&consumerID[i]);if(hThreads[i]==NULL)return-1;}while(g_continue){if(getchar()){//按回车后终止程序运行g_continue=false;}}return0;}6(2)生产者生产一个产品的函数://生产一个产品。简单模拟了一下,仅输出新产品的ID号voidProduce(){std::cerrProducing++ProductID***;std::cerrSucceedstd::endl;}(3)把新生产的产品放入缓冲区的函数://把新生产的产品放入缓冲区voidAppend(){std::cerrAppendingaproduct***;g_buffer[in]=ProductID;in=(in+1)%SIZE_OF_BUFFER;std::cerrSucceedstd::endl;}(4)输出缓冲区当前的状态的函数://输出缓冲区当前的状态for(inti=0;i{std::couti:g_buffer[i];if(i==in)std::cout--生产;if(i==out)std::cout--消费;std::coutstd::endl;}从缓冲区中取出一个产品的函数://从缓冲区中取出一个产品voidTake(){std::cerrTakingaproduct***;ConsumeID=g_buffer[out];out=(out+1)%SIZE_OF_BUFFER;利用信号量解决生产者消费者问题7std::cerrSucceedstd::endl;}(5)输出缓冲区当前的状态的函数://输出缓冲区当前的状态for(inti=0;i{std::couti:g_buffer[i];if(i==in)std::cout--生产;if(i==out)std::cout--消费;std::coutstd::endl;}}(6)消耗一个产品的函数://消耗一个产品voidConsume(){std::cerrConsumingConsumeID***;std::cerrSucceedstd::endl;}3.生产者和消费者算法(1)生产者算法://生产者DWORDWINAPIProducer(LPVOIDlpPara){while(g_continue){WaitForSingleObject(g_hFullSemaphore,INFINITE);WaitForSingleObject(g_hMutex,INFINITE);Produce();Append();Sleep(1500);ReleaseMutex(g_hMutex);ReleaseSemaphore(g_hEmptySemaphore,1,NULL);8}return0;}(2)消费者算法://消费者DWORDWINAPIConsumer(LPVOIDlpPara){while(g_continue){WaitForSingleObject(g_hEmptySemaphore,INFINITE);WaitForSingleObject(g_hMutex,INFINITE);Take();Consume();Sleep(1500);ReleaseMutex(g_hMutex);ReleaseSemaphore(g_hFullSemaphore,1,NULL);}return0;}(4)运行结果分析910输入输出数据说明和分析:该程序设置的缓冲区数据长度为20,生产者个数为3,消费者个数为1,程序启动后,生产者先进行生产,当

1 / 11
下载文档,编辑使用

©2015-2020 m.777doc.com 三七文档.

备案号:鲁ICP备2024069028号-1 客服联系 QQ:2149211541

×
保存成功