System V信号量(3)

时间:2022-04-07 15:17:26

用System  V信号量解决哲学家就餐问题:

#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/sem.h>
#include <sys/wait.h>


#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>




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) */
};


#define DELAY (rand() % 5 + 1)
int semid;


#define ERR_EXIT(m) \
        do \
        { \
                perror(m); \
                exit(EXIT_FAILURE); \
        } while(0)


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


return ret;
}




void wait_for_2fork(int no)
{
int left = no;
int right = (no + 1) % 5;


struct sembuf buf[2] = {
{left, -1, 0},
{right, -1, 0}
};


semop(semid, buf, 2);
}


void free_2fork(int no)
{
        int left = no;
        int right = (no + 1) % 5;


        struct sembuf buf[2] = {
                {left, 1, 0},
                {right, 1, 0}
        };


        semop(semid, buf, 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 left = no;
        int right = (no + 1) % 5;
printf("%d is thinking\n", no);
                sleep(DELAY);
                printf("%d is hungry\n", no);
wait_1fork(left);
sleep(DELAY);
wait_1fork(right);
                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);
}


int no = 0;
pid_t pid;
for (i=1; i<5; i++)
{
pid = fork();
if (pid == -1)
ERR_EXIT("fork");


if (pid == 0)
{
no = i;
break;
}
}


philosophere(no);
return 0;
}

makefile:

.PHONY:clean all
CC=gcc
CFLAGS=-Wall -g
BIN=dining
all:$(BIN)
%.o:%.c
$(CC) $(CFLAGS) -c $< -o $@
clean:
rm -f *.o $(BIN)