实验三生产者与消费者汇编.docx
- 文档编号:15509124
- 上传时间:2023-07-05
- 格式:DOCX
- 页数:21
- 大小:141.17KB
实验三生产者与消费者汇编.docx
《实验三生产者与消费者汇编.docx》由会员分享,可在线阅读,更多相关《实验三生产者与消费者汇编.docx(21页珍藏版)》请在冰点文库上搜索。
实验三生产者与消费者汇编
实验三:
生产者与消费者
实验三:
生产者与消费者
一、实验目的
1.学习和掌握操作系统中进程之间的通信;
2.理解和掌握使用信号量机制来是想进程之间的同步和互斥;
3.学习使用创建文件对象,并利用文件映射对象来实现数据通信。
二、实验内容
•一个大小为6的缓冲区,初始为空,每个缓冲区能存放一个长度若为10个字符的字符串。
•2个生产者
–随机等待一段时间,往缓冲区添加数据,
–若缓冲区已满,等待消费者取走数据后再添加
–重复12次
•3个消费者
–随机等待一段时间,从缓冲区读取数据
–若缓冲区为空,等待生产者添加数据后再读取
–重复8次
说明:
•显示每次添加和读取数据的时间及缓冲区的状态
•生产者和消费者用进程模拟,缓冲区用共享内存来实现
三、实验环境
1.Windows下:
Windows8,Visualstudio2013
2.Linux下:
LinuxUbuntu4,gcc
四、程序设计与实现
1.Windows下:
A.主要函数说明:
(1)PROCESS_INFORMATIONStartClone(intnCloneID)
功能:
用来创建5个相同的进程,前两个为生产者,后三两个为消费者,赋予其不同的ID值,返回进程的信息。
(2)CreateSemaphore();
功能:
创建3个信号量:
full,empty,mutex。
来互斥的访问缓冲区,实现通信。
(3)CreateFileMapping()
功能:
在当前运行的进程中创建文件映射对象,来模拟共享缓冲区
MapViewOfFile()
功能:
在此文件映射上创建视图映射到当前应用程序的地址空间
B.程序流程图
开始
初始化:
创建的子进程个数为0
nClone=0;
创建3个信号量:
full,empty,mutex
创建共享内存
创建5个相同的子进程
nClone++
nClone=?
申请缓冲区
P(empty)
P(mutex)
把产品放入缓冲区:
将0置为1
释放缓冲区:
V(mutex)
V(full)
申请缓冲区
P(full)
P(mutex)
从缓冲区取产品:
将1置为0
释放缓冲区:
V(mutex)
V(empty)
0 2 0 随机等待 12次放完了? 随机等待 12次取完了? 等待子进程执行完毕 结束每个子进程 结束 N Y Y N 实验代码如下: Windows: //实验三.cpp: 定义控制台应用程序的入口点。 // #include"stdafx.h" #include #include #include staticHANDLEhMutexMapping=INVALID_HANDLE_VALUE; intnum=0; HANDLElpHandle[10]; structbuf { intnum; intread; intwrite; intbuffer[5]; }; BOOLStartClone() { inti; BOOLbCreateOK; PROCESS_INFORMATIONpi; TCHARszFilename[MAX_PATH]; GetModuleFileName(NULL,szFilename,MAX_PATH); TCHARszCmdLine[MAX_PATH]; for(i=0;i<3;i++) { sprintf(szCmdLine,"\"%s\"consumer%d",szFilename,i); STARTUPINFOsi; ZeroMemory(reinterpret_cast si.cb=sizeof(si); bCreateOK=CreateProcess( szFilename, szCmdLine, NULL, NULL, FALSE, CREATE_DEFAULT_ERROR_MODE, NULL, NULL, &si, &pi); if(! bCreateOK) { returnfalse; } lpHandle[num]=pi.hProcess; num++; } for(i=0;i<2;i++) { sprintf(szCmdLine,"\"%s\"productor%d",szFilename,i); STARTUPINFOsi; ZeroMemory(reinterpret_cast si.cb=sizeof(si); bCreateOK=CreateProcess( szFilename, szCmdLine, NULL, NULL, FALSE, CREATE_DEFAULT_ERROR_MODE, NULL, NULL, &si, &pi); if(! bCreateOK) { returnfalse; } lpHandle[num]=pi.hProcess; num++; } returntrue; } voidParent() { printf("Creatingthechildprocessandwaitedchildprocesstoquit.\n"); hMutexMapping=CreateMutex(NULL,true,"mutex"); HANDLEhMapping=CreateFileMapping( NULL, NULL, PAGE_READWRITE, 0, sizeof(LONG), "map"); if(hMapping! =INVALID_HANDLE_VALUE) { LPVOIDpData=MapViewOfFile( hMapping, FILE_MAP_ALL_ACCESS, 0, 0, 0); if(pData! =NULL) { ZeroMemory(pData,sizeof(LONG)); } structbuf*pnData=reinterpret_cast pnData->read=0; pnData->write=0; pnData->num=0; memset(pnData->buffer,0,sizeof(pnData->buffer)); UnmapViewOfFile(pData); } CreateSemaphore(NULL,3,3,"EMPTY"); CreateSemaphore(NULL,0,3,"FULL"); BOOLbCreateOK=StartClone(); if(! bCreateOK) { //printf("Createchildprocessfailed.\n"); } else { //printf("Createchildprocesssuccess.\n"); } ReleaseMutex(hMutexMapping); } voidProductor(intn) { intj; printf("Productorisrunning.\n"); hMutexMapping=OpenMutex(MUTEX_ALL_ACCESS,true,"mutex"); HANDLEhMapping=OpenFileMapping( FILE_MAP_ALL_ACCESS, NULL, "map"); if(hMapping==INVALID_HANDLE_VALUE) { printf("error\n"); } HANDLEsemEmpty=OpenSemaphore(SEMAPHORE_ALL_ACCESS,FALSE,"EMPTY"); HANDLEsemFull=OpenSemaphore(SEMAPHORE_ALL_ACCESS,FALSE,"FULL"); for(inti=0;i<6;i++) { WaitForSingleObject(semEmpty,INFINITE); SYSTEMTIMEst; GetSystemTime(&st); srand((unsigned)time(0)); Sleep(rand()/6); WaitForSingleObject(hMutexMapping,INFINITE); LPVOIDpFile=MapViewOfFile( hMapping, FILE_MAP_ALL_ACCESS, 0, 0, 0); if(pFile! =NULL) { structbuf*pnData=reinterpret_cast pnData->buffer[pnData->write]=1; pnData->write=(pnData->write+1)%3; pnData->num++; printf("%02d: %02d: %02d生产者[%d]生产成功缓冲区中剩余%d个",st.wHour,st.wMinute,st.wSecond,n,pnData->num); for(j=0;j<3;j++) { printf("%d",pnData->buffer[j]); } printf("\n"); } UnmapViewOfFile(pFile); pFile=NULL; ReleaseSemaphore(semFull,1,NULL); ReleaseMutex(hMutexMapping); } printf("生产者[%d]生产完毕\n",n); } voidConsumer(intn) { intj; printf("Consumerisrunning.\n"); hMutexMapping=OpenMutex(MUTEX_ALL_ACCESS,true,"mutex"); HANDLEhMapping=OpenFileMapping( FILE_MAP_ALL_ACCESS, NULL, "map"); if(hMapping==INVALID_HANDLE_VALUE) { printf("error\n"); } HANDLEsemEmpty=OpenSemaphore(SEMAPHORE_ALL_ACCESS,FALSE,"EMPTY"); HANDLEsemFull=OpenSemaphore(SEMAPHORE_ALL_ACCESS,FALSE,"FULL"); for(inti=0;i<4;i++) { WaitForSingleObject(semFull,INFINITE); SYSTEMTIMEst; GetSystemTime(&st); srand((unsigned)time(0)); Sleep(rand()/6); WaitForSingleObject(hMutexMapping,INFINITE); LPVOIDpFile=MapViewOfFile( hMapping, FILE_MAP_ALL_ACCESS, 0, 0, 0); if(pFile! =NULL) { structbuf*pnData=reinterpret_cast pnData->buffer[pnData->read]=0; pnData->read=(pnData->read+1)%3; pnData->num--; printf("%02d: %02d: %02d消费者[%d]消费成功缓冲区中剩余%d个",st.wHour,st.wMinute,st.wSecond,n,pnData->num); for(j=0;j<3;j++) { printf("%d",pnData->buffer[j]); } printf("\n"); } UnmapViewOfFile(pFile); pFile=NULL; ReleaseSemaphore(semEmpty,1,NULL); ReleaseMutex(hMutexMapping); } printf("消费者[%d]消费完毕\n",n); } intmain(intargc,char**argv) { if(argc>1&&strcmp(argv[1],"productor")==0) { Productor(atoi(argv[2])); } elseif(argc>1&&strcmp(argv[1],"consumer")==0) { Consumer(atoi(argv[2])); } else { Parent(); WaitForMultipleObjects(num,lpHandle,true,INFINITE); } return0; } Linux下代码: //主进程 #include #include #include"head.h" intmain() { intid=semget(SEM_ALL_KEY,3,IPC_CREAT|0660);//创建信号量集合 //初始化信号量集合 semctl(id,SEM_EMPTY,SETVAL,3); semctl(id,SEM_FULL,SETVAL,0); semctl(id,SEM_MUTEX,SETVAL,1); intshmid=createQueue();//创建共享主存 if(shmid<0) { perror("createshmerror."); exit (1); } //生成生产者进程 if(fork()==0) execl("producer","producer1",0); if(fork()==0) execl("producer","producer2",0); //生成消费者进程 if(fork()==0) execl("consumer","consumer1",0); if(fork()==0) execl("consumer","consumer2",0); if(fork()==0) execl("consumer","consumer3",0); //等待子进程 intstat,i; for(i=0;i<5;i++) wait(&stat); removeQueue(shmid);//释放共享主存 return0; } /*生产者*/ #include"head.h" main(intargc,char*argv[]) { structqueue*buf,*out; intsem_id=semget(SEM_ALL_KEY,3,IPC_CREAT|0660); inti,j; buf=getQueue();//打开共享主存 out=buf; for(i=0;i<6;i++) { p(sem_id,SEM_EMPTY);//P(EMPTY),EMPTY开始值为3,表明有三个空余,申请一个之后,有两个空余,当为零时,不再往里面写数据 p(sem_id,SEM_MUTEX);//P(MUTEX),MUTEX开始值为1,表明一次只能运行一个进程 buf->buf++;//产品数+1 (buf+buf->buf)->buf=1;//放入产品后缓冲区置1 //获取当前时间 structtimevalcurtime; gettimeofday(&curtime,NULL); //输出信息 printf("No.%sputproduct%ld: %ld" argv[0],curtime.tv_sec,curtime.tv_usec); printf("Nowthebufferis"); for(j=1;j<=3;j++) printf("%4d",(out+j)->buf); printf("\n"); v(sem_id,SEM_MUTEX);//V(MUTEX) v(sem_id,SEM_FULL);//V(FULL),释放一个FULL,即往里面写了一个数据 //随机sleep一会 intran=random()%5; sleep(ran); } } /*消费者*/ #include"head.h" main(intargc,char*argv[]) { structqueue*buf,*out; intsem_id=semget(SEM_ALL_KEY,3,IPC_CREAT|0660); inti,j; buf=getQueue();//打开共享主存 out=buf; for(i=0;i<4;i++) { p(sem_id,SEM_FULL);//P(FULL)FULL开始值为0,表明开始的时候没有数据,无法取得,当producer释放一个数据时,这里开始有数据 p(sem_id,SEM_MUTEX);//P(MUTEX) (buf+buf->buf)->buf=0;//取出产品后缓冲区置0 buf->buf--;//产品数-1 //获取当前时间 structtimevalcurtime; gettimeofday(&curtime,NULL); //输出信息 printf("No.%sgetproduct%ld: %ld" argv[0],curtime.tv_sec,curtime.tv_usec); printf("Nowthebufferis"); for(j=1;j<=3;j++) printf("%4d",(out+j)->buf); printf("\n"); v(sem_id,SEM_MUTEX);//V(MUTEX) v(sem_id,SEM_EMPTY);//V(EMPTY) //随机等待一段时间 intran=random()%5; sleep(ran); } } Windows运行截图: Linux下截图:
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 实验 生产者 消费者 汇编