操作系统实验之生产者和消费者程序

这是我的操作系统实验课的实验之一,实验要求“实现生产者和消费者程序”。

老师给了我们示例程序,要求我们自己修改调试。程序代码如下,已经在本地linux系统上能够正确运行。

p是模拟生产者,c是模拟消费者,q是退出

操作系统实验之生产者和消费者程序_第1张图片

但是有一点,如果不是用q退出而是中途用ctrl+c的话,再次运行程序就是显示"segment:File exists"

解决的方法是:

ipcs -s 显示已存在的信号量

ipcrm -s 删除指定信号量

操作系统实验之生产者和消费者程序_第2张图片

#include	
#include	
#include	
#include	
#include	
#include	
#include	
#include	"shmpc.h"

/*
 ********************************************************************************
 *         Name:  main
 *  Description:  entry point
 ********************************************************************************
 */

//var used to shared memory
int shmid;
void *myshm;
struct myshm_st *buf;

//var used to semaphore
int semid;

//common var
int i,n;

void producer()
{

	printf ( "Create a Producer Process Success,%d\n",getpid());

	//attach share memory
	myshm=shmat(shmid,NULL,0);
	if(myshm==(void *)-1)
	{
		perror("shmat");
		exit(-1);
	}

	buf=(struct myshm_st *)myshm;

	//produe a product
	for(n=0;nm_count==BUFSIZE)
		{
			printf("[%d/P/%d]:Blocked!\n",getpid(),n);
			sleep(5);
		}
		//P
		struct sembuf action;
		action.sem_num=0;
		action.sem_op=-1;
		action.sem_flg=SEM_UNDO;
		if(semop(semid,&action,1)==-1)
		{
			perror("semop");
			exit(0);
		}
		buf->m_count++;
		buf->m_buf[buf->m_in]='A';
		sleep(1);
		buf->m_in=(buf->m_in+1)%BUFSIZE;
		printf("[%d/P/%d]:",getpid(),n);
		for(i=0;i<10;i++)
		{
			if(buf->m_buf[i]=='A')
				printf("|A");
			else
				printf("| ");
		}
		printf("|\n");

		//V
		action.sem_op=1;
		if(semop(semid,&action,1)==-1)
		{
			perror("semop");
			exit(0);
		}

		sleep(DELT);
	}
	if(shmdt(myshm)==-1)
		perror("shmdt");
	exit(0);
}

void consumer()
{

	printf ( "Create a Consumer Process Success,%d\n",getpid());

	//attach share memory
	myshm=shmat(shmid,NULL,0);
	if(myshm==(void *)-1)
	{
		perror("shmat");
		exit(-1);
	}

	buf=(struct myshm_st *)myshm;

	//consum a product
	for(n=0;nm_count==0)
		{
			printf("[%d/C/%d]:Blocked!\n",getpid(),n);
			sleep(5);
		}

		//P
		struct sembuf action;
		action.sem_num=0;
		action.sem_op=-1;
		action.sem_flg=SEM_UNDO;
		if(semop(semid,&action,1)==-1)
		{
			perror("semop");
			exit(0);
		}

		buf->m_count--;
		buf->m_buf[buf->m_out]=' ';
		buf->m_out=(buf->m_out+1)%BUFSIZE;


		printf("[%d/C/%d]:",getpid(),n);
		for(i=0;i<10;i++)
		{
			if(buf->m_buf[i]=='A')
				printf("|A");
			else
				printf("| ");
		}
		printf("|\n");


		//V
		action.sem_op=1;
		if(semop(semid,&action,1)==-1)
		{
			perror("semop");
			exit(0);
		}

		sleep(DELT);
	}
	if(shmdt(myshm)==-1)
		perror("shmdt");
	exit(0);

}

int main(int argc, char *argv[])
{

	char t;
	int ppid,cpid;
	//create a shared memery
	printf("Begin...\n");
	shmid=shmget(MYKEY,sizeof(struct myshm_st),IPC_CREAT|0770);
	if( shmid==-1 )
	{
		perror("shmget");
		exit(-1);
	}

	//attach shared memory
	myshm=shmat(shmid,NULL,0);
	if(myshm==(void *)-1)
	{
		perror("shmat");
		exit(-1);
	}

	//init shared memory
	buf=(struct myshm_st *)myshm;
	buf->m_count=0;
	buf->m_in=0;
	buf->m_out=0;

	//create a semaphore
	semid=semget(MYKEY,1,IPC_CREAT|IPC_EXCL|0770);
	if( semid==-1 )
	{
		perror("semget");
		exit(0);
	}

	union semun init_val;
	init_val.val=1;
	if( semctl(semid,0,SETVAL,init_val )==-1)
	{
		perror("semctl");
		exit(0);
	}

	for(;;)
	{
		t=getchar();
		switch ( t )
		{
			case 'p' :
				//create a producer process
				ppid=fork();
				if( ppid==0 )
				{
					producer();
				}
				break;
			case 'c':
				cpid=fork();
				if( cpid==0 )
				{
					consumer();
				}
				break;
			case 's':
				//please add stat code here
			case 'q':
				if(shmdt(myshm)==-1)
					perror("shmdt");
				if(shmctl(shmid,IPC_RMID,0)==-1)
					perror("shmctl");
				if(semctl(semid,1,IPC_RMID,NULL)==-1)
					perror("semctl");
				exit(0);
		}
	}

}

shampc.h

/*
 *    Description  limited buffer
 */

#define BUFSIZE 10

#define MYKEY	9000
#define MUTEX	9001
#define FULL	9002
#define EMPTY	9003

#define NSIZE   5	//number of item each child 
#define DELT	1	//interval between two item

struct myshm_st
{
	int m_count;
	int m_in;
	int m_out;
	char m_buf[BUFSIZE];
};

union semun
{
	int              val;    /*  Value for SETVAL */
	struct semid_ds *buf;    /*  Buffer for IPC_STAT, IPC_SET */
	unsigned short  *array;  /*  Array for GETALL, SETALL */
	struct seminfo  *__buf;  /*  Buffer for IPC_INFO
					  (Linux-specific) */
};

 

你可能感兴趣的:(操作系统,信号量)