生产者消费者实验报告-3_第1页
生产者消费者实验报告-3_第2页
生产者消费者实验报告-3_第3页
生产者消费者实验报告-3_第4页
生产者消费者实验报告-3_第5页
已阅读5页,还剩4页未读 继续免费阅读

下载本文档

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

文档简介

操作系统实验报告2012年11月12日学号10081141081008114120姓名宋芳芳王林燕时间11月12日专业计算机科学与技术班级计科二班实验题目:生产者-消费者问题的实现实验目的:1.熟悉临界资源、信号量及PV操作的定义与物理意义;2.了解进程通信的方法;3.掌握进程互斥与进程同步的相关知识;4.掌握用信号量机制解决进程之间的同步与互斥问题;5.实现生产者-消费者问题,深刻理解进程同步问题。实验内容与步骤:实验内容:说明:有界缓冲区内设有5个存储单元,放入/取出的数据项设定为1-5这5个整型数。实验要求:(1)实现生产者消费者问题模拟,显示每次添加和读取数据时缓冲区的状态,生产者和消费者用进程模拟,缓冲区用共享内存来实现。每个生产者和消费者对有界缓冲区进行操作后,即时显示有界缓冲区的全部内容,当前指针位置和生产者/消费者线程的标识符。Buffer(共享内存)生产者进程消费者进程(2)一个大小为5的缓冲区,初始为空;1个生产者:随机等待一段时间,往缓冲区添加数据,若缓冲区已满,等待消费者取走数据后再添加,重复5次。1个消费者:随机等待一段时间,从缓冲区读取数据,若缓冲区为空,等待生产者添加数据后再读取,重复5次。实验原理:(1)通过一个有界缓冲区把生产者消费者联系起来。假定生产者消费者的优先级是相同的,只要缓冲区未满,生产者就可以生产产品并将产品送入缓冲区。类似地,只要缓冲区未空,消费者就可以从缓冲区中取走产品。应该禁止生产者向满的缓冲区送入产品,同时也应该禁止消费者从空的缓冲区中取出产品,这一机制有生产者线程和消费者线程之间的互斥关系来实现。生产者和消费者两进程P和C之间应满足下列两个同步条件:①只有在缓冲池中至少有一个缓冲区已存入消息后,消费者才能从中提取信息,否则消费者必须等待。②只有缓冲池中至少有一个缓冲区是空时,生产者才能把消息放入缓冲区,否则生产者必须等待。为了满足第一个同步条件,设置一个同步信号量full,它代表的资源是缓冲区满,它的初始值为0,它的值为n==5时整个缓冲池满。这个资源是消费者进程所有,消费者进程可以申请该资源,对它施加P操作,生产者进程P对它施加V操作。为了满足第二个同步条件,设置另一个同步信号量empty,它代表的资源是缓冲空区,它的初始值为n,表示缓冲池中所有缓冲区空。信号量full表示可用缓冲区数量,信号量empty表示缓冲区数量,设置整型变量:存入指针in和取出指针out。(2)设置两个资源信号量,其中一个表示空缓冲区的数目,用g_hFullSemaphore表示,其初始值为有界缓冲区的大小SIZE_OF_BUFFER;另一个表示缓冲区中产品的数目,用g_hEmptySemaphore表示,其初始值为0.另外,由于有界缓冲区是一个临界资源,必须互斥使用,所以还需要在设置一个互斥信号量Mutex,初始值为1.(3)程序中各主要函数的功能如下:生成信号量:intsem_creat(key_tkey,intvalue)删除信号量:voiddel_sem(intsemid)p操作intp(intsemid){structsembufsops={0,-1,SEM_UNDO};return(semop(semid,&sops,1));}v操作intv(intsemid){structsembufsops={0,+1,SEM_UNDO};return(semop(semid,&sops,1));}生产者执行的代码:voidproducer(key_tkeyFull,key_tkeyEmpty,key_tkeymutex)消费者执行的代码:voidconsumer(intfull,intempty,intmutex)实验步骤:打开Unix系统,新建Pro.c文件,存入根目录root。点击右键,有新建终端选项,进入vi编辑器。输入指令vipro.c,键入i进入编辑状态,输入如下代码:用gccgcc命令编译源文件pro.c。具体指令为gcc-opropro.c-lrt./pro.c实验结果:程序代码:#include<stdio.h>#include<stdlib.h>#include<unistd.h>#include<sys/types.h>#include<sys/ipc.h>#include<sys/sem.h>#include<sys/mman.h>//提供了共享内存的相关操作#include<fcntl.h>#include<sys/stat.h>unionsemun{intval;structsemid_ds*buf;unsignedshort*array;}arg;//生成信号量intsem_creat(key_tkey,intvalue){unionsemunsem;intsemid;sem.val=value;semid=semget(key,1,IPC_CREAT|0666);if(-1==semid){printf("createsemaphoreerror\n");exit(-1);}semctl(semid,0,SETVAL,sem);returnsemid;}//删除信号量voiddel_sem(intsemid){unionsemunsem;sem.val=0;semctl(semid,0,IPC_RMID,sem);}//p操作intp(intsemid){structsembufsops={0,-1,SEM_UNDO};return(semop(semid,&sops,1));}//v操作intv(intsemid){structsembufsops={0,+1,SEM_UNDO};return(semop(semid,&sops,1));}int*buffer;//int*pData;intin=0,out=0;intvalue_read=0,value_write=0;intfull,empty,mutex;voidproducer(key_t,key_t,key_t);//生产者所执行的代码voidconsumer(int,int,int);intmain(void){ key_tkeyFull,keyEmpty,keymutex; intfd; pid_tpid;void*ptr;//指向共享内存的指针/*shm_open是一个POSIX函数,用来打开或创建一个与“/shm”关联的共享内存区*/ if((fd=shm_open("/shm",O_RDWR|O_CREAT,S_IRUSR|S_IWUSR))==-1) { printf("shm_openerror\n");/*出错提示*/ } if(ftruncate(fd,5*sizeof(int))==-1)/*截短共享内存的长度到我们所需要的长度*/ { printf("ftruncateerror\n"); } if((ptr=mmap(0,5*sizeof(int),PROT_READ|PROT_WRITE,MAP_SHARED,fd,0))==MAP_FAILED)/*将共享内存映射到进程地址空间*/ { printf("mmaperror"); } buffer=(int*)ptr; keyFull=ftok("/",0);keyEmpty=ftok("/",1);keymutex=ftok("/",3);full=sem_creat(keyFull,0);empty=sem_creat(keyEmpty,5);mutex=sem_creat(keymutex,1); switch(pid=fork()) { case-1:/*生成子进程失败*/ break; case0:/*子进程*/ producer(keyFull,keyEmpty,keymutex);/*子进程是生产者*/ sleep(2); break; default: consumer(full,empty,mutex);/*父进程是消费者*/ break;}wait(0);shm_unlink("/shm");/*删除共享内存区,程序中基本上保证了子进程先退出,因此父进程中无wait操作且这部操作放在父进程这里*/ //shmctl(shmid,IPC_RMID,&buf); //del_sem(semid); return0;}/*生产者写5次后退出*/voidproducer(key_tkeyFull,key_tkeyEmpty,key_tkeymutex){full=semget(keyFull,1,0);empty=semget(keyEmpty,1,0);mutex=semget(keymutex,1,0); while(value_write<5)/*退出条件判定*/ {printf("PrepareWrite\n");printf("emptynumP1:%d\n",semctl(empty,0,GETVAL,0)); p(empty);/*是否有空缓冲区,有则占有,无则被挂起,是原子操作*/ printf("emptynumP2:%d\n",semctl(empty,0,GETVAL,0));printf("mutexnum1%d\n",semctl(mutex,0,GETVAL,0));p(mutex);printf("mutexnum2%d\n",semctl(mutex,0,GETVAL,0)); value_write++; buffer[in]=value_write;printf("write%5dtoposition%5d\n",buffer[in],in+1);in=(in+1)%5; printf("mutexnum1%d\n",semctl(mutex,0,GETVAL,0));v(mutex);printf("mutexnum2%d\n",semctl(mutex,0,GETVAL,0)); printf("fullnumV1:%d\n",semctl(full,0,GETVAL,0)); v(full);/*写完一个缓冲区,释放信号量full(值加1)*/printf("fullnumV2:%d\n",semctl(full,0,GETVAL,0));printf("WriteFinish\n");//sleep(1); }}/*消费者读5次后退出*/voidconsumer(intfull,intempty,intmutex){while(value_read<5)/*退出条件判定*/ {printf("PrepareRead\n");printf("fullnumP1:%d\n",semctl(full,0,GETVAL,0)); p(full);/*获取信号量*/ printf("fullnumP1:%d\n",semctl(full,0,GETVAL,0)); printf("mutexnum1%d\n",semctl(mutex,0,GETVAL,0));p(mutex);printf("mutexnum2%d\n",semctl(mutex,0,GETVAL,0)); printf("read%5dfrompositio

温馨提示

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

评论

0/150

提交评论