1. 程式人生 > >作業系統實驗之生產者和消費者程式

作業系統實驗之生產者和消費者程式

這是我的作業系統實驗課的實驗之一,實驗要求“實現生產者和消費者程式”。

老師給了我們示例程式,要求我們自己修改除錯。程式程式碼如下,已經在本地linux系統上能夠正確執行。

p是模擬生產者,c是模擬消費者,q是退出

但是有一點,如果不是用q退出而是中途用ctrl+c的話,再次執行程式就是顯示"segment:File exists"

解決的方法是:

ipcs -s 顯示已存在的訊號量

ipcrm -s 刪除指定訊號量

#include	<stdio.h>
#include	<stdlib.h>
#include	<unistd.h>
#include	<sys/ipc.h>
#include	<sys/shm.h>
#include	<sys/types.h>
#include	<sys/sem.h>
#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;n<NSIZE;n++)
	{
		while(buf->m_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;n<NSIZE;n++)
	{
		while(buf->m_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);
		}
	}

}