生产者程序与流图.docx
《生产者程序与流图.docx》由会员分享,可在线阅读,更多相关《生产者程序与流图.docx(11页珍藏版)》请在冰豆网上搜索。
![生产者程序与流图.docx](https://file1.bdocx.com/fileroot1/2023-6/30/4c395049-3312-47f5-bf43-45b9caf317ba/4c395049-3312-47f5-bf43-45b9caf317ba1.gif)
生产者程序与流图
生产者程序与流图
————————————————————————————————作者:
————————————————————————————————日期:
程序代码:
#include//定义头文件
#include
#include
#include
#include
#include
#definePRODUCER2//宏定义生产者个数,2个
#defineCOSTOMER3//宏定义消费者个数,3个
#defineWRITE_NUM6//宏定义写缓冲次数,6次
#defineREAD_NUM4//宏定义读缓冲次数,4次
#defineSEM_ALL_KEY1342
#defineSEM_EMPTY0
#defineSEM_FULL1
#defineBUF_LENGTH(sizeof(structcontainer_buffer))//宏定义缓冲区大小
#defineBUFFER_NUM3//宏定义缓冲区个数,3个
#defineSHM_MODE0600//宏定义创建和访问标志
//缓冲区结构(循环队列)
structcontainer_buffer//定义共享缓冲区结构
{
charletter[BUFFER_NUM];
inthead;
inttail;
intis_empty;//判断缓冲区是否为空的标志
};
//得到6以内的一个随机数,产生延迟时间
intrandom_num()
{
intt;
srand((unsigned)(getpid()+time(NULL)));
t=rand()%6;
returnt;
}
//P操作,获得使用权
voidp(intsem_id,intsem_num)
{
structsembufsem_buff;
sem_buff.sem_num=sem_num;
sem_buff.sem_op=-1;
sem_buff.sem_flg=0;
semop(sem_id,&sem_buff,1);
}
//得到一个随机字符,模拟产品名字
charrandom_letter()
{
chara;
srand((unsigned)(getpid()+time(NULL)));
a=(char)((char)(rand()%15)+'!
');
returna;
}
//V操作,释放使用权
voidv(intsem_id,intsem_num)
{
structsembufsem_buff;
sem_buff.sem_num=sem_num;
sem_buff.sem_op=1;
sem_buff.sem_flg=0;
semop(sem_id,&sem_buff,1);
}
//主函数
intmain(intargc,char*argv[])
{
intshm_id,sem_id;//定义共享内存段标识变量shm_id,定义信号量标识变量sem_id
intnum_p=0,num_c=0,i,j;//定义生产者和消费者的个数变量,初始化为0
structcontainer_buffer*shmptr;//指向缓冲区结构的指针
charpn;//随机字符,代表产品
time_tnow;//时间变量
pid_tpid_p,pid_c;//进程pid变量
printf("Mainprocessstarts.\n");
sem_id=semget(SEM_ALL_KEY,2,IPC_CREAT|0660);//创建两个信号量,empty,full
semctl(sem_id,SEM_EMPTY,SETVAL,BUFFER_NUM);//索引为SEM_EMPTY的信号量值为3
semctl(sem_id,SEM_FULL,SETVAL,0);//索引为SEM_FULL的信号量值为0
if((shm_id=shmget(IPC_PRIVATE,BUF_LENGTH,SHM_MODE))<0)//申请一个共享主存段,大小为缓冲区大小
{
exit
(1);//失败退出
}
if((shmptr=shmat(shm_id,0,0))==(void*)-1)//将共享段与进程相连
{
exit
(1);//失败退出
}
shmptr->head=0;//初始化缓冲区
shmptr->tail=0;
shmptr->is_empty=1;
while((num_p++){
if((pid_p=fork())<0)//创建一个进程
{
exit
(1);//失败退出
}
//如果是子进程,开始创建生产者
if(pid_p==0)
{
if((shmptr=shmat(shm_id,0,0))==(void*)-1)//将共享段与本进程相连
{
exit
(1);//失败退出
}
for(i=0;i{
p(sem_id,SEM_EMPTY);//p操作,申请使用权,p(empty)
sleep(random_num());//随机等待一段时间
shmptr->letter[shmptr->tail]=pn=random_letter();//在缓冲队列里面放入一个产品
shmptr->tail=(shmptr->tail+1)%BUFFER_NUM;
shmptr->is_empty=0;//更新缓冲区状态为满
now=time(NULL);//取得系统时间
printf("currenttime:
%02d:
%02d:
%02d\t",localtime(&now)->tm_hour,localtime(&now)->tm_min,localtime(&now)->tm_sec);
for(j=(shmptr->tail-1>=shmptr->head)?
(shmptr->tail-1):
(shmptr->tail-1+BUFFER_NUM);!
(shmptr->is_empty)&&j>=shmptr->head;j--)
//输出缓冲区状态
{
printf("%c",shmptr->letter[j%BUFFER_NUM]);
}
printf("\tProducer%dputsaproductnamedas'%c'.\n",num_p,pn);//输出动作序列
fflush(stdout);//清除文件缓存区
v(sem_id,SEM_FULL);//释放对文件的使用权,V(full)
}
shmdt(shmptr);//将共享段与进程之间解除链接
exit(0);//子进程终止
}
}
for(;num_c{
if((pid_c=fork())<0)//创建一个子进程
{
printf("Erroronfork.\n");
exit
(1);//失败退出
}
//如果是子进程,开始创建消费者
if(pid_c==0)
{
if((shmptr=shmat(shm_id,0,0))==(void*)-1)//将共享段与本进程相连
{
printf("Erroronshmat.\n");
exit
(1);//失败退出
}
for(i=0;i{
p(sem_id,SEM_FULL);//p操作,p(full),实现同步
sleep(random_num());//随机等待一段时间
pn=shmptr->letter[shmptr->head];//得到读取的产品标示字符
shmptr->head=(shmptr->head+1)%BUFFER_NUM;
shmptr->is_empty=(shmptr->head==shmptr->tail);//更新缓冲区产品状态
now=time(NULL);//得到系统时间
printf("currenttime:
%02d:
%02d:
%02d\t",localtime(&now)->tm_hour,localtime(&now)->tm_min,localtime(&now)->tm_sec);
for(j=(shmptr->tail-1>=shmptr->head)?
(shmptr->tail-1):
(shmptr->tail-1+BUFFER_NUM);!
(shmptr->is_empty)&&j>=shmptr->head;j--)
//输出缓冲区状态
{
printf("%c",shmptr->letter[j%BUFFER_NUM]);
}
printf("\tConsumer%dgetsaproductnamedas'%c'.\n",num_c,pn);
fflush(stdout);//清除文件缓存区
v(sem_id,SEM_EMPTY);
}
shmdt(shmptr);//解除共享段与本进程的连接
exit(0);
}
}
//主控程序最后退出
while(wait(0)!
=-1);//等待子进程结束
shmdt(shmptr);//接触父进程和共享段的连接
shmctl(shm_id,IPC_RMID,0);//删除共享内存段
semctl(sem_id,IPC_RMID,0);
printf("Mainprocessends.\n");
fflush(stdout);//清除文件缓存区
exit(0);
}
生产者流程图:
消费者流程图:
主程序流程图:
运行结果如下: