操作系统课程设计-多道程序缓冲期协调操作操作系统.doc_第1页
操作系统课程设计-多道程序缓冲期协调操作操作系统.doc_第2页
操作系统课程设计-多道程序缓冲期协调操作操作系统.doc_第3页
操作系统课程设计-多道程序缓冲期协调操作操作系统.doc_第4页
操作系统课程设计-多道程序缓冲期协调操作操作系统.doc_第5页
已阅读5页,还剩10页未读 继续免费阅读

下载本文档

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

文档简介

东莞理工学院城市学院计算机操作系统课程设计题目: 多道程序缓冲区协调操作 专业: 软件工程 年级: 2012级 小组成员: 指导教师: 时间: 2012.12.24 2012.12.26 地点: 东莞理工学院城市学院计算机与信息科学系制2012年 12 月摘要生产者消费者问题是相互合作的进程关系的一种抽象,可以利用信号量机制来解决生产者消费者问题,利用互斥信号量mutex实现进程对缓冲池的互斥使用。利用信号量实现缓冲区管理临界区协调问题。解决由于进程线程共享内存而出现的与时间有关的错误。掌握信号量的基本概念及PV操作的原理,进一步熟悉信号量解决的经典问题,利用信号量的原理实现不同操作系统下同步互斥问题. 在计算机内存中同时存放几道相互独立的程序,使它们在管理程序控制之下,相互穿插的运行。两个或两个以上程序在计算机系统中同处于开始个结束之间的状态。多道程序设计,是在计算机内存中同时存放几道相互独立的程序,使它们在管理程序控制之下,相互穿插的运行。 目录1. 概述32. 课程设计任务及要求32.1 设计任务32.2 设计要求33. 算法及数据结构43.1算法的总体思想43.2 put模块43.2.1 功能43.2.2 数据结构43.2.3 算法63.3 move线程模块63.3.1功能63.3.2 数据结构63.3.3算法83.4get线程模块93.4.1功能93.4.2 数据结构93.4.3算法104. 程序设计与实现114.1 程序流程图114.2 程序代码134.3 实验结果185. 结论196. 收获、体会和建议207. 参考文献201. 概述 在程序中使用多线程时,一般很少有多个线程能在其生命周期内进行并完全独立的操作。更多的情况是一些线程进行某些处理操作,而其他的线程必须对其处理结果进行了解。正常情况下对这种处理结果的了解 应当在其处理任务完成后进行的。如果不采取适当的措施,其他线程往往会在线程处理任务结束前就去访问处理结果,这就很有可能得到有关处理结果的错误的了解.例如,多个线程同时访问同一个全局变量,如果都是读取操作,则不会出现问题。如果一个线程负责改变此变量的值,而其他线程负责同时读取变量内容,则不能保证读取到的数据是经过写线程修改后的。为了确保读线程读取到的是经过修改的变量,就必须在想变量写入数据时就禁止其他线程对其的任何访问,直至赋值过程结束后再接触对其他线程的访问限制。像这种保证线程能了解其他线程任务结束后的处理结果而采取的保护措施即为线程同步。2. 课程设计任务及要求2.1 设计任务设计一个多道程序完成有10个PUT操作要不断循环地向Buffer1送数据,有一个Move操作要不断地将Buffer1的数据取到Buffer2,有20个GET操作要不断地从Buff2中取数据。BUFF1是10,BUFF2的容量是20, PUT、 MOVE、 GET每次操作一个数据,为了在操作的过程中要保证数据不丢失,每个Buffer每次只能接受一个PUT或一个Move或一个Get,多个操作不能同时操作同一BUFFER。分工:谢沛加:查找资料,讨论需要实现的功能,编译主函数,根据网上教程编写线程产生与销毁,加入关键注释让代码有可读性,设计程序的简单界面,与同学积极讨论解决代码中的问题蓝剑 :查找网上相关资料,讨论题目中要实现的程序功能探讨如何实现,与队友积极交流对程序的想法思路,编写文档,2.2 设计要求(1)显示Buffer的操作过程;(2)可以确定Buffer的容量、PUT、GET、MOVE操作的个数;(3)自行确定放数据的速度,取数据的速度;(4)实时显示每个Buffer中数据的个数,已放入Buffer的数据个数,已取的数据个数;(5)程序运行结束,显示汇总数据:a)总的运行时间;b)Buffer中数据的个数;c)已放入BUFFER的数据个数;d)已放已取的数据个数;e)平均buffer中的数据个数。3. 算法及数据结构3.1算法的总体思想首先要解决每个Buffer每次只能接受一个PUT或一个Move或一个Get那么在每一个Buffer中定义一个互斥信号量sem,线程要使用Buffer时,必须等待sem的信号量,如果没有得到的话需一直等待,等待到其他线程释放出sem的信号量第二要解决Buffer间中信号问题,避免Buffer中无数据或满数据时误操作。通过设置iFull初值为o,oFull初值为0,iEmpty初值为10,oEmpty初值20。当进行数据操作时,对信号量进行增加解决第三题目要求要显示出程序运行时,实时显示出Buffer中数据的状态,通过设置全局变量解决例:设置全局变量i_num控制要执行线程的次数,没执行一次加一,当检测到时,执行 exit(0);结束进程 设置全局变量Buffer1_ied监控Buffer已写入的数据个数,每次执行一次put线程则加1,最后可以显示出Buffer1_ied3.2 put模块3.2.1 功能随机产生一个不大于128的随机数,将产生的随机数加入到Buffer1容器中3.2.2 数据结构void put(void *arg)3.2.3 算法3.3 move线程模块3.3.1功能将Buffer1中的数据取到Buffer2中3.3.2 数据结构void move(void *arg)3.3.3算法3.4get线程模块3.4.1功能将Buffer2中的数据取出3.4.2 数据结构void get(void *arg)3.4.3算法4. 程序设计与实现4.1 程序流程图4.2 程序代码#include#include#include#include#include#include#includetime_t start=0; /定义程序开始时间double duration; /计算程序花费时间sem_t iFull,iEmpty; /定义互斥锁信号量sem_t oFull,oEmpty; /定义互斥锁信号量int i_num; /定义要执行的线程数int b=0; /定义全局变量控制程序结束int iIn=0,iOut=0,oIn=0,oOut=0; /定义写入写出Buffer数组中的位置int i_speed,o_speed; /定义程序读取与写入的速度int iBuffer_volume=0,oBuffer_volume=0;/计算Bufeer中数据的个数int Buffer1_ied=0,Buffer1_oed=0; /监控Buffer1中数据写入写出的个数int Buffer2_ied=0,Buffer2_oed=0; /监控Buffer2中数据写入写出的个数sem_t sem1,sem2; /定义互斥信号量char inBuffer10; /定义Buffer1的大小char outBuffer20; /定义Buffer1的大小int data1,data2,data3; /定义要操作的数据void put(void *arg); /put函数说明void move(void *arg); /move函数说明void get(void *arg); /get函数说明void main(int argc,char *argv) int i,j;int *task110;int *task220;pthread_t id110,id2,id320;int ret;printf(请输入当前放入数据速度(范围为110):);scanf(%d,&i_speed);printf(当前放入速度:%dn,i_speed);printf(请输入当前读取数据速度(范围为110):);scanf(%d,&o_speed);printf(当前读取速度:%dn,o_speed);printf(请输入执行操作的次数:);scanf(%d,&i_num);ret=sem_init(&sem1,0,1); /初始化sem1信号量if(ret!=0)perror(sem_init);ret=sem_init(&sem2,0,1); /初始化sem2信号量if(ret!=0)perror(sem_init);ret=sem_init(&iFull,0,0); /初始化buffer1中满信号量if(ret!=0)perror(sem_init);ret=sem_init(&iEmpty,0,10); /初始化buffer1中空信号量if(ret!=0)perror(sem_init);ret=sem_init(&oFull,0,0); /初始化buffer2中满信号量if(ret!=0)perror(sem_init);ret=sem_init(&oEmpty,0,20); /初始化buffer2中空信号量if(ret!=0)perror(sem_init);ret=pthread_create(&id2,NULL,(void *)move,NULL); /初始化move线程if(ret!=0)perror(pthread thread move error.);for(i=0;i10;i+) /初始化10个put线程task1i=(int *)malloc(sizeof(int); /动态存储*task1i=i;ret=pthread_create(&id1i,NULL,(void *)put,(void *)task1i);if(ret!=0)perror(pthread thread put error.);for(j=0;j20;j+) /初始化20个get线程task2j=(int *)malloc(sizeof(int); /动态存储*task2j=j;ret=pthread_create(&id3j,NULL,(void *)get,(void *)task2j);if(ret!=0)perror(pthread thread get error.);for(i=0;i10;i+) pthread_join(id1i,NULL); /等待put线程执行完毕,这里阻塞pthread_join(id2,NULL); /等待move线程执行完毕,这里阻塞for(j=0;ji_num-1)printf( %f secondsn, duration );printf(当前Buffer1中有%d个数据,当前Buffer2中有%d个数据n,iBuffer_volume,oBuffer_volume);printf(已放已取的数据个数有%d个n,Buffer2_oed);printf(平均buffer中的有%.1f个数据n,(double)(iBuffer_volume+oBuffer_volume)/2);exit(0);void move(void *arg)int ret;while(1)sem_wait(&iFull); /等待iFull信号量sem_wait(&sem1); /等待sem1信号量sleep(1); /设置线程睡眠data2=inBufferiOut; /将data2数据冲Buffer1中移出printf(move:iOut=%d,n当前move出Buffer1的数据为:%dn,iOut,data2);iBuffer_volume-; /通过对iBuffer_volume变量的修改,显示Buffer1中的数据个数Buffer1_oed+; /通过对Buffer1_oed变量的修改,显示Buffer中被取得过的数printf(Buffer1中数据的个数为:%d,剩余容量为:%d,已取得%d个数据n,iBuffer_volume,10-iBuffer_volume,Buffer1_oed);iOut=(iOut+1)%10; /控制数组内的元素不超过10sem_post(&sem1); /发送sem1信号量sem_post(&iEmpty); /发送iEmpty信号量sleep(1); /控制程序睡眠sem_wait(&oEmpty); /等待oEmpty信号量sem_wait(&sem2); /等待sem2信号量sleep(1); /控制程序睡眠outBufferoIn=data2; /向Buffer2里发送data2数据printf(mvoe:oIn=%d,n当前move到Buffer2的数据为:%dn,oIn,data2);oBuffer_volume+; /通过对全局变量的修改,监控Buffer2中的数据数Buffer2_ied+; /通过对全局变量的修改,监控Buffer2产生操作的数据数printf(Buffer2中数据的个数为:%d,剩余容量为:%d,已存过%d个数据n,oBuffer_volume,20-iBuffer_volume,Buffer2_ied);oIn=(oIn+1)%20; /控制数组内的元素不超过20sem_post(&sem2); /发送sem2信号量sem_post(&oFull); /发送oFull信号量sleep(1); /控制程序睡眠b+;duration=(double)(clock()-start)*100000000/CLOCKS_PER_SEC;if(bi_num-1)printf( %f secondsn, duration );printf(当前Buffer1中有%d个数据,当前Buffer2中有%d个数据n,iBuffer_volume,oBuffer_volume);printf(已放已取的数据个数有%d个n,Buffer2_oed);printf(平均buffer中的有%.1f个数据n,(double)(iBuffer_volume+oBuffer_volume)/2);exit(0);void get(void *arg)int *threadid2;threadid2=(int *)arg;while(1)sem_wait(&oFull); /等待oFull信号量sem_wait(&sem2); /等待sem2信号量sleep(11-o_speed); /通过sleep()函数控制线程写入速度data3=outBufferoOut; /将data3数据冲Buffer2中移出printf(get%d:oOut=%d,n当前从Buffer2中get到的数据为:%dn,*threadid2,oOut,data3);oBuffer_volume-; /通过对全局变量的修改,监控Buffer2中的数据数Buffer2_oed+; /通过对全局变量的修改,监控Buffer2取得的数据数printf(Buffer2中数据的个数为:%d,剩余容量为:%d,已取得%d个数据n,oBuffer_volume,20-iBuffer_volume,Buffer2_oed);oOut=(oOut+1)%20; /控制数组内的元素不超过20sem_post(&sem2); /发送sem2信号量sem_post(&oEmpty); /发送oEmpty信号量sleep(1); /通过sleep()函数控制线程睡眠b+; /对全局变量进行修改duration=(double)(clock()-start)*100000000/CLOCKS_PER_SEC;if(bi_num-1)printf( %f secondsn, duration );printf(当前Buffer1中有%d个数据,当前Buffer2中有%d个数据n,iBuffer_volume,oBuffer_volume);printf(已放已取的数据个数有%d个n,Buffer2_oed);printf(平均buffer中的有%.1f个数据n,(double)(iBuffer_volume+oBuffer_volume)/2);exit(0);4.3 实验结果5. 结论整个程序的设计过程中出现了很多问题,比如在设计过程中该设计几个类,各个类该完成什么样的功能,如何实现各个功能,一个类如何调用另一个类中的变量、如何处理事件等等许多问题,在几天的认真思考后,一一解决了,做的课题虽然不是很庞大,但却很锻炼人,在代码设计过程中,对MFC面向对象的思想有了更深入的了解,程序中用到了很多操作系统的思想,如P,V操作,信号量的互斥与实现,线程的概念,对这些概念理解的更加透彻了,几天的设计过程中也看到了自己的不足,如Red Hat Linux-VMware不能熟练运用,在以后的学习中应更加努力、这次课程设计虽然只有短短的几天,但却为我们未来做毕业设计及开发软件打下了基础,意义重大。对于编程,体会到一点非常重要,那就是拿到一个程序要求后首先要构想它的整体框架,然后想好每部分怎么实现,并且在编写代码时要注意编程习惯、编程风格,要有良好的可读性,所以注释是非常重要的。6. 收获、体会和建议谢沛加:通过这次课程设计,我学到了线程的创建与修改,信号量在程序中的应用,注意到了许多课本上没有提到的东西,例如,编译有线程的程序是,要在后面加上-lpthread程序才可以编译通过,否者会报错。通过这次设计,我得到了一个很好的理论联系实际的机会,程序都是分成一个个小的模块然后组装成需要的系统。有些代码看上去没什么问题,但是实际运行起来就是不出正

温馨提示

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

评论

0/150

提交评论