实验三生产者与消费者.docx
- 文档编号:30355520
- 上传时间:2023-08-13
- 格式:DOCX
- 页数:20
- 大小:189.47KB
实验三生产者与消费者.docx
《实验三生产者与消费者.docx》由会员分享,可在线阅读,更多相关《实验三生产者与消费者.docx(20页珍藏版)》请在冰豆网上搜索。
实验三生产者与消费者
实验三:
生产者与消费者
一、实验目的
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)Create()
功能:
在当前运行的进程中创建文件映射对象,来模拟共享缓冲区
MapViewOfFile()
功能:
在此文件映射上创建视图映射到当前应用程序的地址空间
B.程序流程图
实验代码如下:
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;
TCHARsz[MAX_PATH];
GetModule(NULL,sz,MAX_PATH);
TCHARszCmdLine[MAX_PATH];
for(i=0;i<3;i++)
{
sprintf(szCmdLine,"\"%s\"consumer%d",sz);
STARTUPINFOsi;
ZeroMemory(reinterpret_cast
si.cb=sizeof(si);
bCreateOK=CreateProcess(
sz,
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",sz);
STARTUPINFOsi;
ZeroMemory(reinterpret_cast
si.cb=sizeof(si);
bCreateOK=CreateProcess(
sz,
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=Create(
NULL,
NULL,
PAGE_READWRITE,
0,
sizeof(LONG),
"map");
if(hMapping!
=INVALID_HANDLE_VALUE)
{
LPVOIDpData=MapViewOfFile(
hMapping,
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));
UnmapViewOf);
}
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=Open(
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);
LPVOIDp(
hMapping,
0,
0,
0);
if(p)
{
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");
}
UnmapViewOf);
p;
ReleaseSemaphore(semFull,1,NULL);
ReleaseMutex(hMutexMapping);
}
printf("生产者[%d]生产完毕\n",n);
}
voidConsumer(intn)
{
intj;
printf("Consumerisrunning.\n");
hMutexMapping=OpenMutex(MUTEX_ALL_ACCESS,true,"mutex");
HANDLEhMapping=Open(
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);
LPVOIDp(
hMapping,
0,
0,
0);
if(p)
{
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");
}
UnmapViewOf);
p;
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文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 实验 生产者 消费者