精校版生产者程序与流程图Word文档下载推荐.docx
《精校版生产者程序与流程图Word文档下载推荐.docx》由会员分享,可在线阅读,更多相关《精校版生产者程序与流程图Word文档下载推荐.docx(10页珍藏版)》请在冰豆网上搜索。
#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;
a=(char)((char)(rand()%15)+'
!
'
);
returna;
//V操作,释放使用权
voidv(intsem_id,intsem_num)
structsembufsem_buff;
sem_buff.sem_op=1;
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)//将共享段与进程相连
}
shmptr—〉head=0;
//初始化缓冲区
shmptr->
tail=0;
shmptr—>
is_empty=1;
while((num_p++)〈PRODUCER)//循环创建2个生产者
if((pid_p=fork())〈0)//创建一个进程
{
//如果是子进程,开始创建生产者
if(pid_p==0)
if((shmptr=shmat(shm_id,0,0))==(void*)-1)//将共享段与本进程相连
exit
(1);
for(i=0;
i〈WRITE_NUM;
i++)//循环尝试在缓冲区内放入数据为WRITE_NUM次
p(sem_id,SEM_EMPTY);
//p操作,申请使用权,p(empty)
sleep(random_num());
//随机等待一段时间
shmptr-〉letter[shmptr—>
tail]=pn=random_letter();
//在缓冲队列里面放入一个产品
tail=(shmptr—>
tail+1)%BUFFER_NUM;
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<
COSTOMER;
num_c++)//循环创建COSTOMER个生产者
if((pid_c=fork())<
0)//创建一个子进程
printf("
Erroronfork。
//如果是子进程,开始创建消费者
if(pid_c==0)
if((shmptr=shmat(shm_id,0,0))==(void*)—1)//将共享段与本进程相连
Erroronshmat。
\n”);
//失败退出
i<
READ_NUM;
i++)//循环读READ_NUM次
p(sem_id,SEM_FULL);
//p操作,p(full),实现同步
sleep(random_num());
pn=shmptr—>
letter[shmptr—>
head];
//得到读取的产品标示字符
head=(shmptr-〉head+1)%BUFFER_NUM;
is_empty=(shmptr—〉head==shmptr—>
tail);
//更新缓冲区产品状态
now=time(NULL);
//得到系统时间
%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--)
//输出缓冲区状态
%c”,shmptr—〉letter[j%BUFFER_NUM]);
printf(”\tConsumer%dgetsaproductnamedas'
%c'
。
,num_c,pn);
v(sem_id,SEM_EMPTY);
shmdt(shmptr);
//解除共享段与本进程的连接
exit(0);
//主控程序最后退出
while(wait(0)!
=-1);
//等待子进程结束
//接触父进程和共享段的连接
shmctl(shm_id,IPC_RMID,0);
//删除共享内存段
semctl(sem_id,IPC_RMID,0);
printf(”Mainprocessends.\n"
生产者流程图:
生产者线程开始
资源信号量P操作
互斥信号量P操作
生产一个产品
把产品送入缓冲区
互斥信号量V操作
资源信号量V操作
等待队列中有消费者线程
线程自我阻塞
添加到等待队列
未通过
通过
唤醒对头的消费者线程
生产者线程结束
Y
N
消费者流程图:
消费者线程开始
从缓冲区取出一个产品
消费一个产品
等待队列中有生产者线程
唤醒对头的生产者线程
消费者线程结束
主程序流程图:
运行结果如下: