1、操作系统课设报告操作系统课程设计报告题目: 生产者-消费者问题 专 业: 网络工程 班 级: 网络111 学 号: 201110314003 姓 名: 吴超 上海海事大学信息工程学院2013年 12月 15日目 录1. 课程设计任务描述与要求 12.系统总体结构描述和主要数据结构说明 13.课程设计报告内容 34.总结 20附录:程序使用说明 211. 课程设计任务描述与要求1.1 任务描述程序首先读入data文件,根据文件内容建立相应数量的线程,类型为P的线程为生产者,类型为C的线程为消费者;建立一个链表,作为缓冲区,用来存放生产者生产的产品,每个产品占用一个链表结点,消费者从该链表中读取产
2、品信息。1.2 任务要求每个线程根据文件中定义的等待时间,调用Sleep()函数休眠,然后根据“生产或消费产品的数量”字段生产或消费产品;若链表中无产品可以消费,那么消费者需要等待。每次放入或消费产品成功后,向result结果文件中写入一行记录,记录格式如下:线程编号、类型、本次生产或消费产品的数量。生产者和消费者信息存放在data文件中,格式如下:1P 332C 523P 814P 725C 826C 93各数据的含义如下:线程编号类型等待时间 (秒)生产或消费产品的数量1P (生产者)332C (消费者)523P (生产者)814P (生产者)735C (消费者)826C (消费者)123
3、2.系统总体结构描述和主要数据结构说明2.1 系统总体结构描述设计了两个主要函数:生产者函数、消费者函数;设计了三个信号量:full信号量 ,判断缓冲区是否有值,初值为0;empty信号量,判断缓冲区是否有空缓冲区,初值为缓冲区数;mutex信号量作为互斥信号量,用于互斥的访问缓冲区。生产者函数通过执行P操作信号量empty减1,判断缓冲区是否有空。有空则互斥的访问缓冲区并放入数据,然后释放缓冲区,执行操作,信号量full加1。消费者函数执行P操作,信号量full减1,判断是否有数据,有则互斥的访问缓冲区并取走数据,然后释放缓冲区,执行操作,empty信号量加1。3.课程设计报告内容3.1 模
4、块功能该实验主要分为三大模块:1. 主程序,创建并控制程序的流程,其中控制线程的活动以及信号量的操作,如图3-1-1所示;2.生产者模块:生产者对缓冲区的操作,如图3-1-2所示;3.消费者模块:消费者对缓冲区的操作,如图3-1-3所示。3.2 详细流程图图3-1-1 主程序 图3-1-2生产者 图3-1-3消费者通过分析,我们已经了解到了可以采用信号量来解决n个进程的临界区问题,这n个进程共享一个信号量mutex(mutual exclusion),并初始化为1。每个进程Pi的组织结构如下图。由于本系统我们研究的是有限缓冲区(Bounded-Buffer)的生产者消费者问题。而且根据初始条件
5、可知,该缓冲区内有20个缓冲项,每个缓冲项存储一个整形数。信号量mutex提供了对缓冲池访问的互斥要求,并初始化为1。信号量empty和full分别用来表示空缓冲项和满缓冲项的数量。信号量empty初始化为20,而信号量full初始化为0;生产者进程和消费者进程的代码如图。注意生产者和消费者之间的对称性可以这样来理解代码:生产者为消费者生产满缓冲项,或消费者为生产者生产空缓冲项。3.3程序清单和详细注释 #include #include#include#include#include#include#include #include#includeusing namespace std; c
6、onst int ArraySize=100;const int Buffer_Number=10; HANDLE empty, full, mutex;char *produce10 = Product_1, Product_2, Product_3, Product_4, Product_5, Product_6, Product_7, Product_8, Product_9, Product_10;struct Buffer int arrayBuffer_Number; int in,out; buffer;struct ProcParam int threadID; char ty
7、pe; double wait_time; int count;/生产者线程unsigned _stdcall Producer (void* arg) ProcParam *param; /定义一个param数组,数组的每个单元存放一个对应线程的参数 param=(ProcParam*)arg; int nextp; int produce_num; int count = param-count; int t=param-wait_time; printf(线程号码%d是 %c,生产中.正在生产%d个n,param-threadID, param-type,count); while (c
8、ount-) Sleep(t); produce_num = rand() %10; printf(线程%d: 产出产品:%sn, param-threadID, produceproduce_num); WaitForSingleObject(empty, -1); WaitForSingleObject(mutex, -1); nextp = buffer.in; buffer.in = (buffer.in + 1) % Buffer_Number; printf(线程%d: 正在向array%d丢产品:%sn, param-threadID, nextp, produceproduce
9、_num); ofstream outFile; /同时将该信息写入磁盘的某txt文件中 ,该函数要#include outFile.open(result.txt,ios:app) ; /该txt 文件名可自己命名,第1次open时磁盘 中没有该文件,系统会创建一个空白的。 outFileThread ID=threadID 类别:type 生产数量:1 ; outFilecount; int t=param-wait_time; while(count-) printf(线程号码%d是 %c: 消费中.n, param-threadID,param-type); WaitForSingle
10、Object(full, -1); WaitForSingleObject(mutex, -1); nextc = buffer.out; buffer.out = (buffer.out + 1) % Buffer_Number; con_num = buffer.arraynextc; printf(线程%d: 正在消费位于编号array%d的产品:%sn, param-threadID, nextc, producecon_num); ofstream outFile; /同时将该信息写入磁盘的某txt文件中 ,该函数要#include outFile.open(result.txt,i
11、os:app) ; /该txt 文件名可自己命名,第1次open时磁盘 中没有该文件,系统会创建一个空白的。 outFileThread ID=threadID 类型:type 消费数量:1 ; outFileparami.threadID; inFileparami.type; inFileparami.wait_time; inFileparami.count; i+; inFile.get(); threadnumber=0; totalThreads=0; int w=i; for(i=0;iw;i+) if(parami.type=P) totalThreads+; ThreadNu
12、mthreadnumber=i+1; hThreadthreadnumber = (HANDLE)_beginthreadex(NULL, 0, Producer, (void*)¶mthreadnumber, 0, &threadIDi); threadnumber+; else totalThreads+; ThreadNumthreadnumber=i+1; hThreadthreadnumber = (HANDLE)_beginthreadex(NULL, 0, Consumer, (void*)¶mthreadnumber, 0, &threadIDi); threa
13、dnumber+; /等待所有的生产者和消费者执行完毕 WaitForMultipleObjects(totalThreads, hThread, true, INFINITE); /关闭所有打开的句柄 for(i=0; itotalThreads; i+) CloseHandle(hThreadi); CloseHandle(mutex); CloseHandle(empty); CloseHandle(full); printf(程序即将结束。n); getchar(); return 0;3.4程序执行结果截图3.4.1 生产者消费者截图图3-4-1创建线程截图3.4.2 自动生成记录截
14、图 图3-4-2 自动生成记录截图4.总结本次的实验是在刚刚接触到操作系统这门课之后,伴随着操作系统这门课的学习,对于这门课的认识也更加深刻,包括此次做的实验内容,生产者消费者问题也有了一定的认识。生产者进程和消费真进程共享一个有若干数据位置的缓冲区,缓冲区中有n个存放数据的位置,生产者生产产品放入缓冲区,而消费从缓冲中取产品消费,只要缓冲未满,生产者就可以将生产的产品放入缓冲,这种同步规则同时也就表明,如果缓冲区产品满,没有空的位置,则生产者就只能等待消费者取走产品,如果缓冲中没有产品,消费者就不能取产品消费,只能等待生产者放入产品。为解决生产者和消费者进程同步的问题,设置两个信号灯full
15、和empty。这里,信号灯有两个功能:首先它是资源生产和消费的计数器,其次,它是生产者和消费者之间的同步器。信号灯full表示缓冲中存放的产品的数量,初始值为0,每当生产者生产一个产品放入缓冲后。就执行v(full)操作,就是加1操作,表示缓冲区中加入一个产品,每当消费者在取走产品前,执行p(full)操作,其作用是判断缓冲中是否有产品,如果有,则取走一个产品。P操作使得产品数量减一。另外,由于有界缓冲区是一个临界资源,必须互斥使用,因此,需要设置一个互斥灯信号mutex,其初始值为1.本来对于这个问题不是很明白,但是经过问老师和同学的交流,终于找到了方法,用了上面的方法来解决这个问题。感觉到自己对于这方面的知识还有所欠缺,必须认真努力的好好学习。这次的课程设计是大学生活中相当有意义的一次。参考书目:1 刘腾红、骆正华,计算机操作系统(北京,清华大学出版社,2008年;2 张坤。姜立秋、赵慧然,操作系统实验教程(北京,清华大学出版社,2008年;3 汤小丹、梁红兵、哲凤屏、汤子瀛,计算机操作系统,西安电子科技大学出版社,2007年。
copyright@ 2008-2022 冰豆网网站版权所有
经营许可证编号:鄂ICP备2022015515号-1