1. 程式人生 > >用訊號量解決哲學家就餐問題

用訊號量解決哲學家就餐問題

#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/mman.h>
#include <string.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <string.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <sys/wait.h>
#define ERR_EXIT(m)\
	do\
	{\
		perror(m);\
		exit(EXIT_FAILURE);\
	}while(0)

int semid;
#define DELAY (rand() % 5 + 1 )
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) */
																									              };
}






int sem_p(int semid)
{
	struct sembuf sb = {0,-1,0};
	int ret = semop(semid, &sb,1);
	if (ret == -1)
		ERR_EXIT("sem_p");
	return ret;
}


int sem_v(int semid)
{
	struct sembuf sb = {0,1,0};
	int ret = semop(semid, &sb,1);
	if (ret == -1)
		ERR_EXIT("sem_p");
	return ret;
}
void wait_for_2fork(int no)
{
	int left = no;
	int right = (no+1)%5;
	struct sembuf sb[2] = 
	{
		{left, -1, 0},
		{right, -1, 0}
	};
	semop(semid, sb, 2);
}


void free_2fork(int no)
{
	int left = no;
	int right = (no+1)%5;
	struct sembuf sb[2] = 
	{
		{left, 1, 0},
		{right, 1, 0}
	};
	semop(semid, sb, 2);
}
void philosophere(int no)
{
	srand(getpid());
	for (;;)
	{
		printf("%d is thinking!\n", no);
		sleep(DELAY);
		printf("%d is hungry!\n", no);
		wait_for_2fork(no);
		printf("%d is eating!\n", no);
		sleep(DELAY);
		free_2fork(no);
	}
}
int main(int argc, char *argv[])
{
	semid = semget(IPC_PRIVATE, 5, IPC_CREAT | 0666);
	if (semid == -1)
		ERR_EXIT("semget");
	union semun su;
	su.val = 1;
	int i;

	for (i = 0; i < 5; i++)
	{
		semctl(semid,i ,SETVAL,su);
	}
	pid_t pid;
	int no;
	for (i = 0; i < 5; i++)
	{
		pid = fork();
		if (pid == -1)
			ERR_EXIT("fork");
		if (pid == 0)
		{
			no = i;
			break;
		}
	}
	philosophere(no);
	return 0;
}