您好,欢迎访问三七文档
当前位置:首页 > 临时分类 > 生产者与消费者的问题-----操作系统课程设计
1闽江学院计算机系网络操作系统课程设计设计内容:进程机制与并发程序设计——linux下生产者与消费者的问题实现目录:一、设计内容····························3二、设计思想····························4三、系统结构····························5四、PV操作代码··························5五、C++程序代码·························6六、运行结果截图························9七、参考文献····························112八、实验总结····························11一、设计内容进程机制与并发程序设计————linux下生产者与消费者的问题实现1.实验目的(1)掌握基本的同步互斥算法,理解生产者和消费者同步的问题模型。(2)了解linux中多线程的并发执行机制,线程间的同步和互斥。2、实验环境:C/C++语言编译器3、实验要求(1)创建生产者和消费者线程在linux环境下,创建一个控制台进程,在此进程中创建n个线程来模拟生产者或者消费者。这些线程的信息由本程序定义的“测试用例文件”中予以指定。该文件的格式和含义如下:31P32P43C414P25C3124第一行说明程序中设置几个临界区,其余每行分别描述了一个生产者或者消费者线程的信息。每一行的各字段间用Tab键隔开。不管是消费者还是生产者,都有一个对应的线程号,即每一行开始字段那个整数。第二个字段用字母P或者C区分是生产者还是消费者。第三个字段表示在进入相应线程后,在进行生产和消费动作前的休眠时间,以秒计时;这样做的目的是可以通过调整这一列参数,控制开始进行生产和消费动作的时间。如果是代表生产者,则该行只有三个字段。如果代表消费者,则该行后边还有若干字段,代表要求消费的产品所对应的生产者的线程号。所以务必确认这些对应的线程号存在并且该线程代表一个生产者。(2)生产和消费的规则在按照上述要求创建线程进行相应的读写操作时,还需要符合以下要求:3①共享缓冲区存在空闲空间时,生产者即可使用共享缓冲区。②从上边的测试数据文件例子可以看出,某一生产者生产一个产品后,可能不止一个消费者,或者一个消费者多次地请求消费该产品。此时,只有当所有的消费需求都被满足以后,该产品所在的共享缓冲区才可以被释放,并作为空闲空间允许新的生产者使用。③每个消费者线程的各个消费需求之间存在先后顺序。例上述测试用例文件包含一行信息“5C3l24”,可知这代表一个消费者线程,该线程请求消费1,2,4号生产者线程生产的产品。而这种消费是有严格顺序的,消费1号线程产品的请求得到满足后才能继续往下请求2号生产者线程的产品。④要求在每个线程发出读写操作申请、开始读写操作和结束读写操作时分别显示提示信息。(3)相关基础知识本实验所使用的生产者和消费者模型具有如下特点:本实验的多个缓冲区不是环形循环的,也不要求按顺序访问。生产者可以把产品放到目前某一个空缓冲区中。消费者只消费指定生产者的产品。在测试用例文件中指定了所有的生产和消费的需求,只有当共享缓冲区的数据满足了所有关于它的消费需求后,此共享缓冲区才可以作为空闲空间允许新的生产者使用。本实验在为生产者分配缓冲区时各生产者间必须互斥,此后各个生产者的具体生产活动可以并发。而消费者之间只有在对同一产品进行消费时才需要互斥,同时它们在消费过程结束时需要判断该消费对象是否已经消费完毕并清除该产品。linux用来实现同步和互斥的实体。在linux中,常见的同步对象有:信号量(Semaphore)、互斥量(Mutex)、临界段(CriticalSection)等。使用这些对象都分为三个步骤,一是创建或者初始化:接着请求该同步对象,随即进入临界区,这一步对应于互斥量的上锁;最后释放该同步对象,这对应于互斥量的解锁。这些同步对象在一个线程中创建,在其他线程中都可以使用,从而实现同步互斥。二、设计思想生产者进程与消费者进程是经典的同步互斥关系。系统创建两类进程:proceducer()和consumer(),分别用来描述生产者和消费者的行为。生产者与消费者问题是指若干进程通过循环缓冲池区交换数据。如下图所示,生产者进程不断向循环缓冲池区中写入数据(即生产数据),而消费者进程不断从循环缓冲池区中读出数据(即消费数据)。循环缓冲池共有N个缓冲区,缓冲区可以暂存一个产品,任何时刻只能有一个进程课对循环缓冲池进行操作。所有生产者和消费者要协调工作,以完成数据的交换。只要有空缓冲区,生产者就可以把产品送入缓冲区;只要有满缓冲区,消费者就可以从缓冲区中取走物品。4为了解决生产者和消费者问题,应该设置信号量和变量如下:full:满缓冲区资源信号量,初值为0;empty:空缓冲区资源信号量,初值为n;in:生产者指针,初值均为0;out:消费者指针,均为0;mutex:缓冲区操作的互斥信号量,初值为1三、系统结构PCB*readyhead=NULL,*readytail=NULL;//就绪队列——链表结构PCB*consumerhead=NULL,*consumertail=NULL;//消费者队列PCB*producerhead=NULL,*producertail=NULL;//生产者队列processproc()---给PCB分配内存,产生相应的的进程Pempty()---如果缓冲区满,该进程进入生产者等待队列;linkqueue(exe,&producertail);//把就绪队列里的进程放入生产者队列的尾部执行顺序:Main()---empty---in---full---out---finish当缓冲池为空时,生产者生产产品in缓冲池in=in+1当缓冲池为满时,消费者消费产品out缓冲池out=out+1四、PV操作代码semaphoreempty=n;semaphorefull=0;semaphoremutex=1;messagebuffer[n];intin=0;5intout=0;voidmain(){parbegin(proceducer(),consumer());}voidproceducer(){do{prodeceanewmeddage;P(empty);P(mutex);sendanewmessagetobuffer[in];in=(in+1)%n;V(mutex);V(full);}while(true);}voidconsumer(){do{P(full);P(mutex);getamessagefrombuffer[out];out=(out+1)%n;V(mutex);V(empty);comsumeamessage;}while(true);}五、C++程序代码#includewindows.h#includeiostream.h#includemath.h#definerandom(rand()*10000)/RAND_MAX//定义一个随机函数来生产产品,并且使两个顾产品间的时间少于10秒intlongwaiting(0);//正在等待的产品的数目intbuffer;//空位的总数目charempty;//缓冲区空charfull;//缓冲区满intcount(0);//产品的号码数intfinish(0);//生产完毕的产品数目DWORDa;voidproceduce()6{Sleep(10000);cout缓冲区已空!endl;//生产者生产产品函数,用时10秒}voidgetconsum(){Sleep(10001);//产品被生产的函数,为了合理区分生产产品cout第finish个产品被消费,取出endl;}HANDLEMutex=CreateMutex(NULL,FALSE,Mutex);//用来实现进程的互斥HANDLEproceducer=CreateSemaphore(NULL,1,1,proceducer);//定义信号量来进行线程间的同步HANDLEconsumer=CreateSemaphore(NULL,0,3,consum);DWORDWINAPIconsum(LPVOIDpParm2)//消费的线程{WaitForSingleObject(Mutex,INFINITE);//p(mutex)来进行互斥操作count++;//生产的是第几个产品cout第count个产品生产了endl;if(waitingbuffer)//如果缓冲池还有空位{if(waiting!=0){cout此时有waiting+1个产品等待消费endl;}elsecout没有产品在等待endl;//输出有多少人在等待waiting++;cout还有buffer-waiting个空位endl;cout有空区,产品已经进入endl;ReleaseSemaphore(consum,1,NULL);//v(consumer)ResumeThread(consum);//唤醒生产者进程ReleaseMutex(Mutex);//释放互斥量,以便其他线程使用WaitForSingleObject(proceducer,INFINITE);//等待生产getconsum();//消费并取走}else{cout缓冲区已满,第count个产品暂停生产endl;//没有空位,生产者不再生产ReleaseMutex(Mutex);}return0;}DWORDWINAPIproceducers(LPVOIDpParm1)//生产者的线程{while(true)//一直执行{7WaitForSingleObject(consum,INFINITE);//p(customers),等待产品WaitForSingleObject(Mutex,INFINITE);//等待互斥量waiting--;//等待的产品数减一ReleaseSemaphore(proceducer,1,NULL);//释放信号量ResumeThread(proceducer);//唤醒消费进程ReleaseMutex(Mutex);//v(mutex);proceduce();//生产finish++;//消费的产品数加1}return0;}intmain(intargc,char*argv[]){cout请输入缓冲区空位的总数目:;cinbuffer;cout缓冲区共有buffer个空位endl;//设置缓冲区空位数目cout缓冲区空生产产品吗?Y/Nendl;//缓冲区是否空cinempty;while(empty!='y'){coutendl********对不起,缓冲区满!********endl;cout缓冲区已空,生产产品?Y/Nendl;cinempty;}HANDLEhThread1;HANDLEhThread2;hThread2=::CreateThread(NULL,0,proceducers,NULL,0,NULL);//产生一个生产者进程while(full!='y'){Sleep(random);//产品随机进入hThread1=::CreateThread(NULL,0,consum,NULL,a,NULL);coutendl********缓冲区已空,请继续生产********endl;if(finish=10&&waiting==0)//如果完成数超过10并且没有人等待{cout已经为finish个产品了,要停止生产吗?endl;//提示是否关门cinfull;returnfull;}else;}if(full=='y'){cout********对不起,缓冲区已满**
本文标题:生产者与消费者的问题-----操作系统课程设计
链接地址:https://www.777doc.com/doc-6905970 .html