linux生产消费者模型

本文主要分析的是多生产者,多消费者以及多个资源的进程间的同步和互斥机制。

操作系统中我们已经学习过了生产者和消费者之间的同步互斥模型

生产者:

{

生产一个产品;

p(empty);

p(mutex);

产品入buffer;

v(mutex);

v(full);

}

消费者

{

p(full);

p(mutex);

从buffer中取出产品;

v(mutex);

v(empty);

}

在真正编程实现是,采用IPC机制,因此要为生产者和消费者共同使用的变量创建共享内存区域并且将该共享内存区域映射到进程的地址空间中,从而可以直接对该地址空间

进行操作。

而且,在该模型中,使用了三个信号量,因此要采用linux中的信号量集机制。

#include <shm.h>


int main()
{
	int num;
	int shmid_goods,shmid_index,semid;
	char* shmaddr=NULL;
	int *indexaddr=NULL;
	int is_noexist=0;

	num=10;
	//创建货物的共享内存区域,并且链接到进程用户空间。大小为10字节。
	if((shmid_goods=createshm(".",'s',num))==-1)
	{
		if(errno==EEXIST)
		{
			if((shmid_goods=openshm(".",'s'))==-1)
			{
				exit(1);
			}
		}
		else
		{
			perror("create shared memory failed\n");
		        exit(1);
		}
	}
	//返回共享内存区域的标识符
	if((shmaddr=shmat(shmid_goods,(char*)0,0))==(char*)-1)
	{
		perror("attach shared memory error\n");
		exit(1);
	}

	/*创建一个共享内存,用于存放生产者和消费者在buffer中的索引号。
    该索引指向了生产/消费的buffer的索引值。
	*/
	if((shmid_index=createshm(".",'z',2))==-1)
	{
		if(errno==EEXIST)
		{
			if((shmid_index=openshm(".",'z'))==-1)
			{
				exit(1);
			}
		}
		else
		{
			perror("create shared memory failed\n");
		        exit(1);
		}
	}
	else
	{
		is_noexist=1;
	}
	//attach the shared memory to the current process
	if((indexaddr=shmat(shmid_index,(int*)0,0))==(int*)-1)
	{
		perror("attach shared memory error\n");
		exit(1);
	}
	/*
    索引初始化为0
	*/
	if(is_noexist)
	{
		indexaddr[0]=0;
		indexaddr[1]=0;
	}

	
	/*该函数用于生成信号量集,并通过信号量集标识符设置信号量的值
	mutex:1
	empty:10
	full:0
	前两个参数用于生成key。
	*/
	if((semid=createsem(".",'t',3,0))==-1)
	{
		if(errno==EEXIST)
		{
			if((semid=opensem(".",'t'))==-1)
			{
				exit(1);
			}
		}
		else
		{
			perror("semget error:");
			exit(1);
		}
	}
	else
	{
		union semun arg;
	        //seting value for mutex semaphore

         	arg.val=1;
         	if(semctl(semid,0,SETVAL,arg)==-1)
         	{
			perror("setting semaphore value failed\n");
	        	return -1;
            	}
          	//set value for synchronous semaphore
	        arg.val=num;
            	//the num means that the producer can continue to produce num products
          	if(semctl(semid,1,SETVAL,arg)==-1)
            	{
			perror("setting semaphore value failed\n");
	         	return -1;
         	}
           	//the last semaphore's value is default
           	//the default value '0' means that the consumer is not use any product now
      	}

	
	int goods=0;
	while(1)
	{
		p(semid,1);
		sleep(3);
		p(semid,0);
		//producer is producing a product
		goods=rand()%10;
		///将货物buffer中编号为indexaddr[0]的buffer中放入货物
		shmaddr[indexaddr[0]]=goods;
		printf("producer:%d produces a product[%d]:%d\n",getpid(),indexaddr[0],goods);
		///同时索引值+1。
		indexaddr[0]=(indexaddr[0]+1)%10;
		v(semid,0);
		sleep(3);
		v(semid,2);
	}

}



#include <shm.h>


int main()
{
	int num;
	int shmid_goods,shmid_index,semid;
	char* shmaddr=NULL;
	int *indexaddr=NULL;
	int is_noexist=0;

	num=10;
	//创建货物的共享内存区域,并且链接到进程用户空间。大小为10字节。
	if((shmid_goods=createshm(".",'s',num))==-1)
	{
		if(errno==EEXIST)
		{
			if((shmid_goods=openshm(".",'s'))==-1)
			{
				exit(1);
			}
		}
		else
		{
			perror("create shared memory failed\n");
		        exit(1);
		}
	}
	//返回共享内存区域的标识符
	if((shmaddr=shmat(shmid_goods,(char*)0,0))==(char*)-1)
	{
		perror("attach shared memory error\n");
		exit(1);
	}

	/*创建一个共享内存,用于存放生产者和消费者在buffer中的索引号。
    该索引指向了生产/消费的buffer的索引值。
	*/
	if((shmid_index=createshm(".",'z',2))==-1)
	{
		if(errno==EEXIST)
		{
			if((shmid_index=openshm(".",'z'))==-1)
			{
				exit(1);
			}
		}
		else
		{
			perror("create shared memory failed\n");
		        exit(1);
		}
	}
	else
	{
		is_noexist=1;
	}
	//attach the shared memory to the current process
	if((indexaddr=shmat(shmid_index,(int*)0,0))==(int*)-1)
	{
		perror("attach shared memory error\n");
		exit(1);
	}
	/*
    索引初始化为0
	*/
	if(is_noexist)
	{
		indexaddr[0]=0;
		indexaddr[1]=0;
	}

	
	/*该函数用于生成信号量集,并通过信号量集标识符设置信号量的值
	mutex:1
	empty:10
	full:0
	前两个参数用于生成key。
	*/
	if((semid=createsem(".",'t',3,0))==-1)
	{
		if(errno==EEXIST)
		{
			if((semid=opensem(".",'t'))==-1)
			{
				exit(1);
			}
		}
		else
		{
			perror("semget error:");
			exit(1);
		}
	}
	else
	{
		union semun arg;
	        //seting value for mutex semaphore

         	arg.val=1;
         	if(semctl(semid,0,SETVAL,arg)==-1)
         	{
			perror("setting semaphore value failed\n");
	        	return -1;
            	}
          	//set value for synchronous semaphore
	        arg.val=num;
            	//the num means that the producer can continue to produce num products
          	if(semctl(semid,1,SETVAL,arg)==-1)
            	{
			perror("setting semaphore value failed\n");
	         	return -1;
         	}
           	//the last semaphore's value is default
           	//the default value '0' means that the consumer is not use any product now
      	}

	
	int goods=0;
	while(1)
	{
		p(semid,1);
		sleep(3);
		p(semid,0);
		//producer is producing a product
		goods=rand()%10;
		///将货物buffer中编号为indexaddr[0]的buffer中放入货物
		shmaddr[indexaddr[0]]=goods;
		printf("producer:%d produces a product[%d]:%d\n",getpid(),indexaddr[0],goods);
		///同时索引值+1。
		indexaddr[0]=(indexaddr[0]+1)%10;
		v(semid,0);
		sleep(3);
		v(semid,2);
	}

}



#include <shm.h>


int main(int argc,char **argv)
{
	int num;
	int shmid_goods,shmid_index,semid;
	char* shmaddr=NULL;
	int* indexaddr=NULL;
	int is_noexist=0;

	num=10;
	//create a shared memory as goods buffer
	//注意,生产消费者的相同的共享区域用了同样的参数,
	//所以会禅城同样的key值。
	if((shmid_goods=createshm(".",'s',num))==-1)
	{
		if(errno==EEXIST)
		{
			if((shmid_goods=openshm(".",'s'))==-1)
			{
				exit(1);
			}
		}
		else
		{
			perror("create shared memory failed\n");
		        exit(1);
		}
	}
	//attach the shared memory to the current process
	if((shmaddr=shmat(shmid_goods,(char*)0,0))==(char*)-1)
	{
		perror("attach shared memory error\n");
		exit(1);
	}

	//create a shared memory as index
	if((shmid_index=createshm(".",'z',2))==-1)
	{
		if(errno==EEXIST)
		{
			if((shmid_index=openshm(".",'z'))==-1)
			{
				exit(1);
			}
		}
		else
		{
			perror("create shared memory failed\n");
		        exit(1);
		}
	}
	else
	{
		is_noexist=1;
	}
	//attach the shared memory to the current process
	if((indexaddr=shmat(shmid_index,(int*)0,0))==(int*)-1)
	{
		perror("attach shared memory error\n");
		exit(1);
	}
	if(is_noexist)
	{
		indexaddr[0]=0;
		indexaddr[1]=0;
	}

	//create a semaphore set including 3 semaphores
	if((semid=createsem(".",'t',3,0))==-1)
	{
		if(errno==EEXIST)
		{
			if((semid=opensem(".",'t'))==-1)
			{
				exit(1);
			}
		}
		else
		{
			perror("semget error:");
			exit(1);
		}
	}
	else
	{
		union semun arg;
	        //seting value for mutex semaphore
         	arg.val=1;
         	if(semctl(semid,0,SETVAL,arg)==-1)
         	{
			perror("setting semaphore value failed\n");
	        	return -1;
            	}
          	//set value for synchronous semaphore
	        arg.val=num;
            	//the num means that the producer can continue to produce num products
          	if(semctl(semid,1,SETVAL,arg)==-1)
            	{
			perror("setting semaphore value failed\n");
	         	return -1;
         	}
           	//the last semaphore's value is default
           	//the default value '0' means that the consumer is not use any product now
      	}

	int goods=0;
	while(1)
	{
		p(semid,2);
		sleep(1);
		p(semid,0);
		///取出一个货物。
		goods=shmaddr[indexaddr[1]];
		printf("consumer:%d consumes a product[%d]:%d\n",getpid(),indexaddr[1],goods);
		//索引值加一
		indexaddr[1]=(indexaddr[1]+1)%num;
		v(semid,0);
		sleep(1);
		v(semid,1);
	}

}




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值