1、多道程序缓冲区协调操作操作系统报告苏州科技学院天平学院操作系统课程设计报告多道程序缓冲区协调操作专业年级计算机工程2010班级计算机工程1022计算机工程1022学号10321072091032107202姓名刘志愿金志献成绩指导教师陆卫忠 2012年7月4日任务分配情况姓名承担的任务金志献编写主函数 编译执行程序并修改刘志愿协助修改程序 编写报告多道程序缓冲区协调操作一概述1.目的:(1)了解提出信号量的背景 (2)掌握信号量的基本概念及 PV 操作的原理 (3)进一步熟悉信号量解决的经典问题 (4)利用信号量的原理实现不同操作系统下同步互斥问题2.主要完成的任务:有10个Put操作要不断循
2、环地向InBuffer送数据,有一个Move操作要不断地将InBuffer的数据取到OutBuffer,有20个GET操作要不断地从OutBuff中取数据。InBuffer的容量是10, OutBuff的容量是20, Put、 Move、 Get每次操作一个数据,为了在操作的过程中要保证数据不丢失,每个Buffer每次只能接受一个Put或一个Move或一个Get,多个操作不能同时操作同一Buffer(即需要互斥操作)。设计一个多道程序完成上述操作。试用、原语(或Wait、Signal)协调Put、 Move、Get的操作,并说明每个信号量的含义、初值和值的范围。3.使用的开发工具:VMware
3、 Workstation,Red Hat Linux2.4.20-84.解决的主要问题:需求分析 利用信号量实现缓冲区管理临界区协调问题。解决由于进程线程共享内存而出 现的与时间有关的错误。二使用的基本概念和原理2.1. 信号量:为解决多进程线程同步与互斥问题,让两个或多个多道进程线程通过特殊的变量展开交互。2.2. 线程:是进程的一个实体,是进程上下文中执行的代码序列,是被系统调度的基本单元。2.3. 进程:进程是正在运行的程序实体,并且包括这个运行的程序中占据的所有系统资源。2.4. 互斥与同步:进程的同步与互斥是指进程在推进时的相互制约关系。 进程同步:它主要源于进程合作,是进程间共同完
4、成一项任务时直接发生相互作用的关系。 进程互斥:它主要源于资源共享,是进程之间的间接制约关系。三总体设计生产者消费者问题是相互合作的进程关系的一种抽象,可以利用信号量机制来解决生产者消费者问题,利用互斥信号量mutex实现进程对缓冲池的互斥使用。对信号量的操作只能通过两个原子操作:Wait(s)和Signal(s).Wait(s)是等待信号的操作,进行S=S-1操作;Signal(s)是发送信号的操作,进行S=S+1操作。wait 若s-1后仍大于或等于零,则进程继续执行;若s-1后小于零,则该进程被阻塞后进入与该信号相对应的队列中,然后转进程调度;若相加结果大于或等于零,则从该信号的等待队列
5、中唤醒一等待进程,然后再返回原进程继续执行或转进程调度如下图所示,有10个PUT(相当于生产者)操作要不断循环地向Buffer1送数据,有一个Move(相当于搬运者)操作要不断地将Buffer1的数据取到Buffer2,有20个GET(相当于消费者)操作要不断地从Buff2中取数据。BUFF1是10,BUFF2的容量是20, PUT、 MOVE、 GET每次操作一个数据,为了在操作的过程中要保证数据不丢失,每个Buffer每次只能接受一个PUT或一个Move或一个Get,多个操作不能同时操作同一BUFFER。设计一个多道程序完成上述操作。试用、原语协调PUT、 MOVE、GET的操作,并说明每
6、个信号量的含义、初值和值的范围。设计总体流程图如下:四详细设计4.1线程规划我们创建三类线程:(1)PUT线程(往BUFFER1里放数据,相当于生产者)。(2)MOVE线程(从BUFFER1里取数据并放到BUFFER2里,相当于搬运者)。(3)GET线程(从BUFFER2里取数据,相当于消费者)。每类线程可由用户自行设定线程的个数。4.2信号量的设置需要设置六个信号量full1 empty1 buff1 full2 empty2 buff2。各信号量含义及初值如下:full1表示buffer1是否有数据,初值为0;empty1表示buffer1是否有空间,初值为m;buff1表示buffer1
7、是否可操作,初值为1;full2表示buffer2是否有数据,初值为0;empty2表示buffer2是否有空间,初值为n;buff2表示buffer2是否可操作,初值为1。五编码设计 1.开发环境为Linux,我们在进入RedHat Linux 后输入startx进入图形界面,在任务菜单里可以寻找终端,即可进行代码编写与执行。 2.程序源代码如下/* 定义头文件 */#include #include #include #include #include #include #include /* 定义头变量 */sem_t iFull,iEmpty;sem_t oFull,oEmpty;in
8、t iIn=0,iOut=0,oIn=0,oOut=0;sem_t sem1,sem2;char inBuffer10;char outBuffer20;int data1,data2,data3;void put(void *arg);void move(void *arg);void get(void *arg);/* mian函数 */main(int argc, char *argv) int i,j; int *task110; int *task220; pthread_t id110,id2,id320; int ret; /*初始化信号量imutex为1*/ ret=sem_i
9、nit(&sem1,0,1); if(ret!=0) perror(sem_init); /*初始化信号量omutex为1*/ ret=sem_init(&sem2,0,1); if(ret!=0) perror(sem_init); /*初始化信号量iFull为1*/ ret=sem_init(&iFull,0,0); if(ret!=0) perror(sem_init); /*初始化信号量iEmpty为10*/ ret=sem_init(&iEmpty,0,10); if(ret!=0) perror(sem_init); /*初始化信号量oFull为0*/ ret=sem_init(&
10、oFull,0,0); if(ret!=0) perror(sem_init); /*初始化信号量oEmpty为20*/ ret=sem_init(&oEmpty,0,20); if(ret!=0) perror(sem_init); /*创建三个线程*/ /move线程 ret=pthread_create(&id2,NULL,(void *)move, NULL); if(ret!=0) perror(pthread thread move error.); /put线程 for(i=0;i10;i+) task1i = (int *)malloc(sizeof(int); *task1i
11、 = i; ret=pthread_create(&id1i,NULL,(void *)put,(void *)task1i); if(ret!=0) perror(pthread thread put error.); /get线程 for(j=0;j20;j+) 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;
12、i+) pthread_join(id1i,NULL); pthread_join(id2,NULL); for(j=0;j20;j+) pthread_join(id3j,NULL); exit(0);/* put操作线程函数 */void put(void *arg) int i; int *threadid1; threadid1 = (int *)arg; srand(time(NULL); while(1) sleep(1); data1= rand() % 128; /*信号量减一,P操作*/ sem_wait(&iEmpty); sem_wait(&sem1); sleep(1)
13、; printf(put%d:iIn=%d,nThe data put into the inBuffer is:%dn,*threadid1,iIn,data1); inBufferiIn=data1; iIn=(iIn+1)%10; /*信号量加一,V操作*/ sem_post(&sem1); sem_post(&iFull); sleep(2); /* move操作线程函数 */void move(void *arg) int ret; while(1) /* move操作将数据取出inBuffer缓冲区 */ sem_wait(&iFull); sem_wait(&sem1); sle
14、ep(1); data2=inBufferiOut; printf(move:iOut=%d,nThe data get out of the inBuffer is:%dn,iOut,data2); iOut=(iOut+1)%10; sem_post(&sem1); sem_post(&iEmpty); sleep(1); /* move操作将数据放入outBuffer缓冲区 */ sem_wait(&oEmpty); sem_wait(&sem2); sleep(1); outBufferoIn=data2; printf(move:oIn=%d,nThe data put into t
15、he outBuffer is:%dn,oIn,data2); oIn=(oIn+1)%20; sem_post(&sem2); sem_post(&oFull); sleep(1); /* get操作线程函数 */void get(void *arg) int ret; int *threadid2; threadid2 = (int *)arg; while(1) sem_wait(&oFull); sem_wait(&sem2); sleep(1); data3=outBufferoOut; printf(get%d:oOut=%d,nThe data get out of the ou
16、tBuffer is:%dn,*threadid2,oOut,data3); oOut=(oOut+1)%20; sem_post(&sem2); sem_post(&oEmpty); sleep(1); 六测试时出现过的问题及解决方法1. 一开始写程序时无从下手,后来经过老师指点将本程序的P.V原语写出,程序就可以按照P.V原语的顺序往下写。2. 一开始不明白程序的线程操作上锁与解锁的含义,后来经老师指导得知线程互斥与同步就是信号量的互斥与同步,创建信号量就可以表示出线程间的关系。3. 出现段错误,后改成输入的数据有随机数生成函数产生即解决此问题。 一开始不明白程序的线程操作上锁与解锁的含义
17、,后来经老师指导得知线程互斥与同步就是信号量的互斥与同步,创建信号量就可以表示出线程间的关系。4. 编译时为出错,但在执行时出现段错误,后改成输入的数据有随机数生成函数产生即解决此问题。 七实验结果实验结果如下:八总结本软件利用Red Hat Linux-VMware实现多线程的同步,用户可以直接观察多线程的运行,协调,并且可以设置线程的个数,缓冲区的容量,以及线程的速度。整个程序的设计过程中出现了很多问题,比如在设计过程中该设计几个类,各个类该完成什么样的功能,如何实现各个功能,一个类如何调用另一个类中的变量、如何处理事件等等许多问题,在几天的认真思考后,一一解决了,做的课题虽然不是很庞大,
18、但却很锻炼人,在代码设计过程中,对MFC面向对象的思想有了更深入的了解,程序中用到了很多操作系统的思想,如P,V操作,信号量的互斥与实现,线程的概念,对这些概念理解的更加透彻了,几天的设计过程中也看到了自己的不足,如Red Hat Linux-VMware不能熟练运用,在以后的学习中应更加努力、这次课程设计虽然只有短短的几天,但却为我们未来做毕业设计及开发软件打下了基础,意义重大。从这次课程设计中我们认识到,在开始写代码前,一定要有个整体的规划,如设计几个类,每个类能完成什么样的功能,应该设计几个变量,几个方法,各个方法能完成的功能等等,如果没有整体的规划,在代码编写过程中就无从下手,或者写了一半发现这样写不能实现要求的功能。在写代码时,最好遵循编程规范,否则代码的修改与维护会很困难,在和别人共同编写程序时更应该注意这一点。八参考文献1 汤小丹,梁红兵,哲凤屏,汤子瀛.计算机操作系统. 西安:西安电子科技大学出版社,2007.
copyright@ 2008-2023 冰点文库 网站版权所有
经营许可证编号:鄂ICP备19020893号-2