版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
武汉理工大学计算机科学与技术学院操作系统课程设计学号:0121410880202课内实践报告课程名称操作系统学院计算机科学与技术学院专业软件工程专业班级软件1401姓名指导教师刘军2016--2017学年第一学期目录设计题目与要求 31.设计目的、总体设计思想与环境工具 31.1设计目的 31.2总体设计思想概述 31.3设计环境及工具 41.3.1设计环境 41.3.2设计工具 42.设计方案 42.1设计内容 42.2设计原理 42.3流程图 63.详细设计 83.1数据结构 83.2算法说明 83.2.1同步机制算法 83.2.2具体算法实现 93.3具体程序实现 113.3.1生产者方法 113.3.2消费者方法 123.3.3多线程实现 134.运行结果及分析 154.1运行结果图 154.2结果分析 154.3源程序 154.4调试过程 205.自我评价与总结 216.参考文献 22评分标准 23设计题目与要求设计题目:实现生产者消费者(Bounded–BufferProblem)问题要求:通过研究Linux的线程机制和信号量实现生产者消费者(BoundedBuffer)问题的并发控制。实验条件要求:每人一台与Linux主机联网的Windows主机,普通用户权限。1.设计目的、总体设计思想与环境工具1.1设计目的1)通过编程实现生产者与消费者问题,了解进程同步的概念,理解信号量机制的原理;2)掌握运用信号量解决进程同步问题的方法,学会运用进程的同步与互斥解决生产者与消费者的冲突问题;3)通过研究linux的线程机制和信号量实现生产者消费者问题的并发控制。1.2总体设计思想概述=1\*Arabic1)生产者-消费者问题是一种同步问题的抽象思维;2)计算机系统中的每个进程都可以消费或产生某类资源。当系统中某一进程使用某一资源时,可以看做是消耗,且该进程成为消费者;3)当某个进程释放资源时,可以看做是一个生产者。1.3设计环境及工具1.3.1设计环境Ubuntu15.10.1.3.2设计工具GCC编译器,vi编译器.2.设计方案2.1设计内容在同一个进程的空间内执行的两个线程,生产者生产物品,然后将物品放置在一个空缓冲区中供消费者线程消费。消费者线程从缓冲区中获得物品,然后释放缓冲区,当生产者线程生产物品时,如果没有空缓冲区可用,那么生产者线程必须等待消费者线程释放出一个空缓冲区,当消费者线程消费物品时,如果没有满的缓冲区,那么消费者线程将被阻塞,直到新的物品被生产出来,简历缓冲区,生产者生产的产品放入,消费者从中取出产品,如果没有产品,则等待。2.2设计原理要实现生产者与消费者的互斥关系,生产者和消费者进程之间必须满足两个同步条件:1.只有在缓冲池中至少有一个缓冲区已存入消息后,消费者才可以从中提取消息,否则消费者必须等待。2。只有缓冲池中至少有一个缓冲区是空时,生产证才可以把消息放入缓冲区中,否则生产者必须等待。要满足第一个同步条件,设置一个同步信号量full_sem,它的值为20时整个缓冲区满,这个资源是消费者进程所拥有,消费者进程可以申请资源,对它做P操作;另外一个信号量empty_sem,他的初值为20,表示整个缓冲区都是空的。可以用full_sem表示空缓冲区数量,empty_sem表示满缓冲区数量,另外有界缓冲区是一个临界资源,必须互斥是用,所以必须在设置一个互斥信号量mux初值为1。在生产者/消费者问题信号量实现两种功能。首先,他是跟踪资源的生产和消费的计数器,其次,它是协调产品的生产者和消费者之间动作同步的同步器。消费者通过再一指派给它的信号量上做P操作来表示消耗资源。而生产者通过在同一个信号量上做V操作来表示生产资源。而这种信号量的实施中,计数在每次P操作后减1,而在每次V操作后加1.这个计数器的初始值是可以利用的资源数目,当资源不可利用时,将申请资源的进程放置在等待队列中,如果有个资源释放,在等待队列中的第一个进程被唤醒并得到资源的控制权。假定在生产者和消费者之间的公共缓冲区中,具有n个缓冲区,这是可以利用互斥信号量mutex实现各进程对缓冲区的互斥使用,利用信号量empty和full分别表示缓冲池中空缓冲区和满缓冲区的数量,又假定这些生产者和消费者互相等效果求偶,只要缓冲区未满,生产者便可以将消息送入缓冲池,只要缓冲池未空,消费者便可以从缓冲池中取走一个消息。2.3流程图生产一条数据生产一条数据是否可用存储单元是否可用存入一条数据归还使用权数据单元加1,唤醒一个消费者等待资源,阻塞被唤醒等待使用权,阻塞被唤醒无有否图SEQFigure\*ARABIC1生产者流程图是否有数据单元是否有数据单元是否可用取走一条数据归还使用权空单元加1,唤醒一个生产者消费数据等待资源,阻塞被唤醒等待使用权,阻塞被唤醒有是否图SEQFigure\*ARABIC2消费者流程图3.详细设计3.1数据结构#defineN2//消费者或者生产者的数目#defineM10//缓冲数目intin=0;//生产者放置产品的位置intout=0;//消费者取产品的位置intbuff[M]={0};//缓冲初始化为0,开始时没有产品sem_tempty_sem;//同步信号量,当满了时阻止生产者放产品sem_tfull_sem;//同步信号量,当没产品时阻止消费者消费pthread_mutex_tmutex;//互斥信号量,一次只有一个线程访问缓冲intproduct_id=0;//生产者idintprochase_id=0;//消费者id3.2算法说明3.2.1同步机制算法1)P进程不能往“满”的缓冲区中放产品,设置信号量为sem_empty;2)Q进程不能从“空”的缓冲区中取产品,设置信号量为sem_full。3)先设置信号量:sem_empty初值为1,sem_full初值为0实现如下:P:While(true){生产一个产品;P(Sem_empty);送产品到缓冲区;V(sem_full);}Q:while(true){P(sem_full);从缓冲区去产品V(sem_empty);消费产品;}P操作的主要动作是:sem减1;若sem减1后仍大于或等于零,则进程继续执行;若sem减1后仍小于零,则该进程被阻塞后与该信号所对应的队列中,然后转入进程调度;V操作的主要动作时:Sem加1;若相加结果大于零;③若相加结果小于或者等于零,则从该信号的等待队列中唤醒一等待队列,然后再返回原进程继续执行或转入进程调度。3.2.2具体算法实现Semaphoremutex=1;//定义互斥信号量Semaphoreempty=n;//定义同步信号量Semaphorefull=0;item[n];//定义缓冲池Intin=0;//生产者放置位置Intout=0;//消费者放置位置Producer()//生产者{While(true){Produceaniteminnext_product;//生产者产生数据Swait(empty,mutex);//等待缓冲区空信号量Array[in]=next_product;//将数据放入缓冲池In=(in+1)%n;Ssignal(mutex,full);}}Consumer()//消费者{While(true){Swait(full,mutex);//等待缓冲池满信号量Next_consumer=array[out];//从缓冲池取出数据Out=(out+1)%n;Ssignal(mutex,empty);Consumetheproductinnext_consumer;//等待下一个消费者取出数据}}3.3具体程序实现3.3.1生产者方法在生产者方法的实现中,先产生一个数据,然后判断缓冲池空信号量,如果缓冲池至少有一个为空则将先将缓冲池上锁,然后将数据放入缓冲池,将放入数据位置指针后移,放入数据后将缓冲池解锁;如果缓冲池为满,则生产者线程进入阻塞状态,进入进程调度队列,并等待缓冲池空信号量。/*生产者方法*/void*product(){intid=++product_id;while(1){//用sleep的数量可以调节生产和消费的速度,便于观察sleep(1);//sleep(1);sem_wait(&empty_sem);//等待缓冲池空信号量pthread_mutex_lock(&mutex);//对缓冲池上锁in=in%M;printf("product%din%d.like:\t",id,in);//显示生产者IDbuff[in]=1;//将数据放入缓冲区print();//打印存数结果++in;//写入位置指针后移pthread_mutex_unlock(&mutex);//对缓冲池解锁sem_post(&full_sem);//等待缓冲池满信号量}}3.3.2消费者方法在消费者方法实现中,首先判断缓冲池满信号量,如果缓冲池中不为空,则进行取数操作,并对缓冲池上锁,取数后,显示消费者ID,随后对缓冲池解锁;如果缓冲池为空,则不对缓冲池操作,消费者线程进入阻塞状态,进入线程调度队列。/*消费者方法*/void*prochase(){intid=++prochase_id;while(1){//用sleep的数量可以调节生产和消费的速度,便于观察sleep(1);//sleep(1);sem_wait(&full_sem);//等待缓冲池满指针pthread_mutex_lock(&mutex);//对缓冲池上锁out=out%M;printf("prochase%din%d.like:\t",id,out);//答应消费者IDbuff[out]=0;print();//答应信息++out;//取数指针后移pthread_mutex_unlock(&mutex);//对缓冲池解锁sem_post(&empty_sem);}}3.3.3多线程实现在线程的创建时,可以用函数pthread_create用来创建一个线程,它的原型为:intpthread_create__P((pthread_t*__thread,__constpthread_attr_t*__attr,void*(*__start_routine)(void*),void*__arg));
第一个参数为指向线程标识符的指针,第二个参数用来设置线程属性,第三个参数是线程运行函数的起始地址,最后一个参数是运行函数的参数。这里,我们的函数thread不需要参数,所以最后一个参数设为空指针。第二个参数我们也设为空指针,这样将生成默认属性的线程函数pthread_join用来等待一个线程的结束。函数原型为:
externintpthread_join__P((pthread_t__th,void**__thread_return));
第一个参数为被等待的线程标识符,第二个参数为一个用户定义的指针,它可以用来存储被等待线程的返回值。这个函数是一个线程阻塞的函数,调用它的函数将一直等待到被等待的线程结束为止,当函数返回时,被等待线程的资源被收回。一个线程的结束有两种途径,一种是像我们上面的例子一样,函数结束了,调用它的线程也就结束了;另一种方式是通过函数pthread_exit来实现。它的函数原型为:externvoidpthread_exit__P((void*__retval))__attribute__((__noreturn__));
唯一的参数是函数的返回代码,只要pthread_join中的第二个参数thread_return不是NULL,这个值将被传递给thread_return。最后要说明的是,一个线程不能被多个线程等待,否则第一个接收到信号的线程成功返回,其余调用pthread_join的线程则返回错误代码ESRCH。//创建N个生产者线程for(i=0;i<N;i++){ret[i]=pthread_create(&id1[i],NULL,product,(void*)(&i));//将生产者方法创建成线程if(ret[i]!=0){printf("product%dcreationfailed\n",i);//打印线程创建信息exit(1);}}//创建N个消费者线程for(i=0;i<N;i++){ret[i]=pthread_create(&id2[i],NULL,prochase,NULL);//将消费者方法创建成线程if(ret[i]!=0){printf("prochase%dcreationfailed\n",i);//打印消费者线程创建信息exit(1);}}//销毁线程for(i=0;i<N;i++){pthread_join(id1[i],NULL);pthread_join(id2[i],NULL);}exit(0);}4.运行结果及分析4.1运行结果图4.2结果分析从运行结果截图中可以看到:程序创建了5个生产者线程,4个消费者线程。每次生产者线程产生一个数据并存入缓冲池中,每次消费者线程从缓冲池中取出一个数,并且在每次生产者线程产生数据和消费者取出数据后都打印缓冲区中的数据。4.3源程序/**author:JiaJingnan*/#include<stdio.h>#include<stdlib.h>#include<unistd.h>#include<pthread.h>#include<semaphore.h>#defineN2//消费者或者生产者的数目#defineM10//缓冲数目intin=0;//生产者放置产品的位置intout=0;//消费者取产品的位置intbuff[M]={0};//缓冲初始化为0,开始时没有产品sem_tempty_sem;//同步信号量,当满了时阻止生产者放产品sem_tfull_sem;//同步信号量,当没产品时阻止消费者消费pthread_mutex_tmutex;//互斥信号量,一次只有一个线程访问缓冲intproduct_id=0;//生产者idintprochase_id=0;//消费者id/*打印缓冲情况*/voidprint(){inti;for(i=0;i<M;i++)printf("%d",buff[i]);printf("\n");}/*生产者方法*/void*product(){intid=++product_id;while(1){//用sleep的数量可以调节生产和消费的速度,便于观察sleep(1);//sleep(1);sem_wait(&empty_sem);pthread_mutex_lock(&mutex);in=in%M;printf("product%din%d.like:\t",id,in);buff[in]=1;print();++in;pthread_mutex_unlock(&mutex);sem_post(&full_sem);}}/*消费者方法*/void*prochase(){intid=++prochase_id;while(1){//用sleep的数量可以调节生产和消费的速度,便于观察sleep(1);//sleep(1);sem_wait(&full_sem);pthread_mutex_lock(&mutex);out=out%M;printf("prochase%din%d.like:\t",id,out);buff[out]=0;print();++out;pthread_mutex_unlock(&mutex);sem_post(&empty_sem);}}intmain(){pthread_tid1[N];pthread_tid2[N];inti;intret[N];//初始化同步信号量intini1=sem_init(&empty_sem,0,M);intini2=sem_init(&full_sem,0,0);if(ini1&&ini2!=0){printf("seminitfailed\n");exit(1);}//初始化互斥信号量intini3=pthread_mutex_init(&mutex,NULL);if(ini3!=0){printf("mutexinitfailed\n");exit(1);}//创建N个生产者线程for(i=0;i<N;i++){ret[i]=pthread_create(&id1[i],NULL,product,(void*)(&i));if(ret[i]!=0){printf("product%dcreationfailed\n",i);exit(1);}}//创建N个消费者线程for(i=0;i<N;i++){ret[i]=pthread_create(&id2[i],NULL,prochase,NULL);if(ret[i]!=0){printf("prochase%dcreationfailed\n",i);exit(1);}}//销毁线程for(i=0;i<N;i++){pthread_join(id1[i],NULL);pthread_join(id2[i],NULL);}exit(0);}4.4调试过程由于一开始进行linux下的c编程实验并不是多线程的,编译时没有加上-pthread,编译出错;在代码中找错误很久也没有发现错误,后来通过上网查找终于解决了这个问题,也理解了多线程编译-pthread和–lpthread的区别。5.自我评价与总结经过连续几天的努力,、终于完成了这个课程设计,从一开始对这个课程设计题目的
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 2025缝纫机机器租赁合同
- 兰州市政府2025年度合同管理创新试点合同3篇
- 2025年度酒店客房内墙乳胶漆翻新服务合同3篇
- 2025年度知识产权交易及投资合作协议3篇
- 二零二五年度竞业禁止机械租赁与节能技术合同3篇
- 二零二五年度跨国公司股东合伙人战略合作协议3篇
- 二零二五年度航空航天出资入股协议
- 2025年度生态园林景观设计-特色树苗订购与施工合同
- 二零二五年度生物医药研发项目转让合同3篇
- 二零二五年度房产转让合同中的税务筹划及优惠条款协议3篇
- 明亚保险经纪人考试题库答案
- 精心设计“每日一练”探求“轻负高质”练习策略
- 设备维护与故障排除项目设计评估方案
- 针灸推拿学100512练习题库与参考答案
- 常用截面惯性矩与截面系数的计算
- 行车工考试试题
- 小儿头皮静脉输液课件
- 电力电缆高频局放试验报告
- 肺病科主任年度述职汇报
- 2023年福建省晋江市数学七年级第一学期期末学业质量监测试题含解析
- 水利水电工程基础坑隐蔽工程验收证书
评论
0/150
提交评论