⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 barber_ok.c

📁 改进的理发店问题
💻 C
字号:
#include	<sys/types.h>
#include	<sys/ipc.h>
#include	<sys/sem.h>
#include	<sys/shm.h>
#include	<stdio.h>
#include	<unistd.h>

#define	DEFAULT_N		(15+3)	/*没有参数时,缺省为15个顾客和3个理发师*/

/*宏定义wait和signal*/
#define SIGNAL(A,B)			V.sem_num = (A+B);if(semop(semid,&V,1)==-1) { perror("signal fail");exit(1);}
					
#define WAIT(A,B)			P.sem_num = (A+B);if(semop(semid,&P,1)==-1) { perror("wait fail");exit(1);}
				

union	semun
{
	int		val;/*for SETVAL*/
	struct semid_ds *buf;/*for IPC_STAT and IPC_SET*/
	ushort		*array;/*for GETALL and SETALL*/
};

enum
{
	MAX_CAPACITY=0,
	SOFA,
	BARBER_CHAIR,
	CASHIER=5,
	MUTEX,
	CUST_READY=7,
	LEAVE_B_CHAIR=10,
	PAYMENT=13,
	RECEIPT=16,
	FINISHED=19,
	queueLOCK=22
};

static struct	sembuf P = {0,-1,SEM_UNDO},V = {0,1,SEM_UNDO};
			/******wait和signal操作******/
static ushort	start_val[23] = {20,4,1,1,1,1,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1};
			/******23个信号量的初值******/
static int		semid,shmid;/*信号量ID和共享内存ID*/

struct QueueType
{
	int	value[4];
	int out;
	int	in;
};


void	enqueue(struct QueueType* q,int val )/*入队列*/
{
	if((q->in+1)%4==q->out)
	{
		printf("queue is full\n");
		return;
	}
	else
	{
		q->value[q->in] = val;
		q->in = (q->in+1)%4;
		printf("Barber %d(his pid is %d) is ready ,he wants to send No.%d to a customer\n",val,getpid(),val);
	}
			
}
void	dequeue(struct QueueType* q,int *val,int i)/*出队列*/
{
	if(q->out==q->in)
	{
		printf("queue is empty\n");
		return;
	}
	else{
		*val = q->value[q->out];
		q->out = (q->out+1)%4;
		printf("Customer %d has got the No.%d\n",i,*val);
	}
}
void	enter_shop(int j)
{
	printf("Customer %d enter the barber shop.\n",j);
}

void	sit_on_sofa(int j)
{
	printf("Customer %d sit on the sofa.\n",j);
}

void	get_up_from_sofa(int j)
{
	printf("Customer %d get up from sofa.\n",j);
}

void	sit_in_barber_chair(int j)
{
	printf("Customer %d sit in the barber chair.\n",j);
}

void	leave_barber_chair(int j)
{
	printf("Customer %d leave the barber chair.\n",j);
}

void	pay(int  j)
{
	printf("Customer %d pay the money.\n",j);
}

void	exit_shop(int j)
{
	printf("Customer %d exit shop.\n",j);
}

void	accept_pay(int bnum)
{
	printf("Barber %d accept the payment .\n",bnum);
	printf("Barber %d has given the receipt .\n",bnum);
}

void	cut_hair(int bnum)
{
	sleep(0.5);
	printf("Barber %d is cutting hair.\n",bnum);
	printf("Barber %d has finished cutting hair.\n",bnum);
}

void	customer(struct QueueType *queue,int i)
{
	int chairnum;/*顾客取得的椅子号码*/
	WAIT(MAX_CAPACITY,0);/*顾客等待进门*/
	enter_shop(i);/*进门*/
	WAIT(SOFA,0);/*等待沙发*/
	sit_on_sofa(i);/*顾客在沙发上等待*/
	WAIT(MUTEX,0);/***有空闲的理发师?***/
	WAIT(queueLOCK,0);/*确保顾客从等待队列中取号码不被打断*/
		//WAIT(MUTEX,0);/***有空闲的理发师?***/
		dequeue(queue,&chairnum,i);/*顾客从队列中取得椅子号码*/
	SIGNAL(queueLOCK,0);/*确保顾客从等待队列中取号码不被打断*/
	WAIT(BARBER_CHAIR,chairnum);/*顾客等待自己号码的理发椅*/
	get_up_from_sofa(i);/*顾客离开沙发*/
	SIGNAL(SOFA,0);/*释放沙发资源*/
	sit_in_barber_chair(i);/*顾客坐上理发椅*/
	SIGNAL(CUST_READY,chairnum);/*顾客告之已在自己号码的理发椅上做好准备*/
	WAIT(FINISHED,chairnum);/*顾客等待理发完成*/
	leave_barber_chair(i);/*顾客离开理发椅*/
	SIGNAL(LEAVE_B_CHAIR,chairnum);/*释放理发椅资源*/
	//WAIT(CASHIER,0);/*等待收银员*/
	pay(i);/*付帐*/
	SIGNAL(PAYMENT,chairnum);/*顾客索要自己的收据*/
	WAIT(RECEIPT,chairnum);/*顾客等待自己应得的收据*/
	exit_shop(i);/*顾客离开理发店*/
	SIGNAL(MAX_CAPACITY,0);/*释放理发店资源*/
}

void	barber(int num,struct QueueType* queue)/*理发师同时兼职收银员*/
{
	WAIT(queueLOCK,0);/*确保理发师发放顾客号码时不被打断*/
		enqueue(queue,num);
		SIGNAL(MUTEX,0);/***已有空闲的理发师***/
	SIGNAL(queueLOCK,0);/*确保理发师发放顾客号码时不被打断*/
	
	while(1) {
		WAIT(CUST_READY,num);/*理发师等待,直到有一个顾客坐上自己的理发椅*/
		cut_hair(num);/*理发过程*/
		SIGNAL(FINISHED,num);/*告之自己的顾客已完成理发*/
		WAIT(LEAVE_B_CHAIR,num);/*理发师等待自己的顾客从理发椅中站起*/
		SIGNAL(BARBER_CHAIR,num);/*理发师在它的理发椅空时发信号*/
		WAIT(PAYMENT,num);/*理发师接着等待收银*/
		accept_pay(num);/*提供收据*/
		SIGNAL(RECEIPT,num);/*告之自己的顾客已发出收据*/
		//SIGNAL(CASHIER,0);/*确保收银过程不被打断*/
		WAIT(queueLOCK,0);/*确保理发师取顾客号码时不被打断*/
			enqueue(queue,num);
		SIGNAL(MUTEX,0);/*已有空闲的理发师*/	
		SIGNAL(queueLOCK,0);/*确保理发师取顾客号码时不被打断*/
	
	}
}

void create_barber(struct QueueType *queue,char* shmptr,pid_t pid)
{
int i;
for( i=0; i<3; i++ )
	{
		if( (pid = fork())<0 )
			perror("fork error");
		else if( pid == 0 )/*子进程*/
				{
				if( (shmptr = (char*) shmat(shmid,(char*)0,0) ) ==(char*)-1) 
					{
					perror("get mermory shmat in child");
					exit(4);
					}
				queue = (struct QueueType *)shmptr;
				barber(i+1,queue);
				shmdt(shmptr);/*删除物理链接*/
				sleep(3);
				_exit(0);
				}
	}
}

void create_customer1(struct QueueType *queue,char* shmptr,pid_t pid,int max)
{
int i;
for( i=0; i<max-3; i++ )
	{
		if( (pid = fork())<0 )
			perror("fork error");
		else if( pid == 0 )/*子进程*/
				{
				if( (shmptr = (char*) shmat(shmid,(char*)0,0) ) ==(char*)-1) 
					{
					perror("get mermory shmat in child");
					exit(4);
					}
				queue = (struct QueueType *)shmptr;
				customer(queue,i+1);
				shmdt(shmptr);/*删除物理链接*/
				sleep(3);
				_exit(0);
				}
	}
}

void create_customer2(struct QueueType *queue,char* shmptr,pid_t pid,int max,int av)
{
int i,upbound;
upbound=2*av+1;
srand( (unsigned int)time(NULL) );
for( i=0; i<max-3; i++ )
	{
		if( (pid = fork())<0 )
			perror("fork error");
		else if( pid == 0 )/*子进程*/
				{
				sleep( rand() % upbound );
				if( (shmptr = (char*) shmat(shmid,(char*)0,0) ) ==(char*)-1) 
					{
					perror("get mermory shmat in child");
					exit(4);
					}
				queue = (struct QueueType *)shmptr;
				customer(queue,i+1);
				shmdt(shmptr);/*删除物理链接*/
				sleep(3);
				_exit(0);
				}
	}
}

int main( int argc, char *argv[] )
{
	pid_t		pid;
	union semun	arg;
	int		order;
	int		max;
	int		i=0;
	key_t		key;
	char 		*shmptr;
	static struct QueueType q;
	struct QueueType 	*queue;

	q.out = q.in = 0;
	
	if(argc>2)
	{
		printf("usage: barbershop [number]\n");
		exit(1);
	}
		
	max = (argc==1)?DEFAULT_N:(atoi(argv[1])+3);
	
	if( (semid = semget( IPC_PRIVATE,23,IPC_CREAT|IPC_EXCL|0600))!=-1)
		/*创建23个信号量,返回信号量ID*/
	{
		arg.array = start_val;
		if( semctl( semid, 0, SETALL, arg )==-1 ) 
		/*按arg.array指向的数组中的值设置该集合中所有信号量的值*/
		{
			perror("semctl error");
			exit(1);
		}
	}
	else if( ( semid = semget( IPC_PRIVATE, 23, 0 ))==-1 ) /*返回信号量ID*/
	{
		perror("semget error");
		exit(2);
	}
	
	if( (shmid = shmget( IPC_PRIVATE, sizeof(q), IPC_CREAT|0600)) != -1) 
	/*创建共享存储区,返回一个共享存储标识符*/
	{
		if( (shmptr = (char*)shmat(shmid,0,0)) == (char*)-1 )/*连接到物理地址*/
		{
			perror("shmptr_parent_attach");
			exit(1);
		}
		memcpy(shmptr,(char*)&q,sizeof(q));/*复制存储区*/
	}
	else
	{
		perror("shmid_parent_creation");
		exit(2);
	}


	printf("\n***** Welcome to XMUCSD Barber Shop, cheap but best in the world! *****\n\n");
	create_barber(queue,shmptr,pid);
	//create_customer1(queue,shmptr,pid,max);
	create_customer2(queue,shmptr,pid,max,2);
	sleep(5);
	shmctl(shmid,IPC_RMID,0);/*从系统中删去共享存储段*/

	while(wait(0) != -1 && i++ < max-3);
	if( semctl(semid,0,IPC_RMID,0)==-1 ) /*删除信号量集合*/
	{
		perror("semctl delete error");
		exit(4);
	}
	return 0;
}


⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -