哲学家问题是操作系统中资源分配的经典问题
linux平台下的系统api不同于Windows下的实现
要求:一个正确的哲学家程序(不会发生死锁)
一个错误的哲学家程序(会发生死锁)
系统环境:ElementaryOS
wrong.c
#include<stdio.h> #include<stdlib.h> #include<sys/ipc.h> #include<sys/msg.h> #include<sys/types.h> #include<unistd.h> #include<errno.h> #include<sys/ipc.h> #include<sys/sem.h> #include<sys/wait.h> #define DELAY (rand() % 5 + 1) #define ERR_EXIT(m) \ do { \ perror(m); \ exit(EXIT_FAILURE); \ } while(0) 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) */ }; //semid ! this is the number of share memory int semid; //waiting for fork here //left and right = the number of sourses void wait_for_1fork(int no) { int left = no; //system defined struct //"first":the current number of pro //"second":resourses -1:wait cannot use;+1:can use //"thired":? struct sembuf buf[1] = { {left, -1, 0}, }; //semop do wait or signal (p/v) //"first": the number of share memory pro //"second":the first point of struct //"third":the number of signal to complete semop(semid, buf, 1); } void wait_for_2fork(int no) { int right = (no + 1) % 5; //system defined struct //"first":the current number of pro //"second":resourses -1:wait cannot use;+1:can use //"thired":? struct sembuf buf[1] = { {right, -1, 0} }; //semop do wait or signal (p/v) //"first": the number of share memory pro //"second":the first point of struct //"third":the number of signal to complete semop(semid, buf, 1); } void free_1fork(int no) { int left = no; //system defined struct //"first":the current number of pro //"second":resourses -1:wait cannot use;+1:can use //"thired":? struct sembuf buf[1] = { {left, 1, 0}, }; semop(semid, buf, 1); } void free_2fork(int no) { int right = (no + 1) % 5; //system defined struct //"first":the current number of pro //"second":resourses -1:wait cannot use;+1:can use //"thired":? struct sembuf buf[1] = { {right, 1, 0} }; semop(semid, buf, 1); } void philosopere(int num) { srand(getpid()); for (; ;) { //printf("%d is thinking\n", num); printf("\033[36m%d is thinking\n\033[0m", num); if(num!=0) sleep(DELAY); //printf("%d is hungry\n", num); wait_for_1fork(num); //printf("%d pick up left chopsticks\n", num); printf("\033[31m%d pick up left chopsticks\n\033[0m", num); sleep(DELAY); sleep(DELAY); wait_for_2fork(num); //printf("%d pick up right chopsticks\n", num); printf("\033[34m%d pick up right chopsticks\n\033[0m", num); //printf("%d is eating\n", num); sleep(DELAY); free_1fork(num); //printf("%d return left chopsticks\n", num); printf("\033[33m%d return left chopsticks\n\033[0m", num); sleep(DELAY); free_2fork(num); //printf("%d return right chopsticks\n", num); printf("\033[37m%d return right chopsticks\n\033[0m", num); } } int main() { //use IPC to connect between processes . A new share memory //semget() return the number of share memory //new signal key=0 and never change .So not use key //"first":use IPC_PRIVATE to share memory between relation processes //"second":(size_t)naxSize //"third":(int flag)private:666--read and write ; IPC_CREAT creat new memory semid = semget(IPC_PRIVATE, 5, IPC_CREAT | 0666); if (semid == -1) ERR_EXIT("semget"); union semun su; su.val = 1; for (int i = 0; i < 5; i++) { //creat a new object on "semid" //use i to depart 5 processes semctl(semid, i, SETVAL, su); } int no = 0; //pid_t (Process ID _ Type) Just like int pid_t pid; for (int i = 1; i < 5; i++) { //use fork() to make a copy of father process named with child pro //father.pid>0 and child.pid=0 //after for loop will exist a father and five childs(0-4) pid = fork(); if (pid == -1) ERR_EXIT("fork"); if (pid == 0) { no = i; //break the child process loop to run the philosopere break; } } philosopere(no); return 0; }
right.c
#include<stdio.h> #include<stdlib.h> #include<sys/ipc.h> #include<sys/msg.h> #include<sys/types.h> #include<unistd.h> #include<errno.h> #include<sys/ipc.h> #include<sys/sem.h> #include<sys/wait.h> #define DELAY (rand() % 5 + 1) #define ERR_EXIT(m) \ do { \ perror(m); \ exit(EXIT_FAILURE); \ } while(0) 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) */ }; //semid ! this is the number of share memory int semid; //waiting for fork here //left and right = the number of sourses void wait_for_2fork(int no) { int left = no; int right = (no + 1) % 5; //system defined struct //"first":the current number of pro //"second":resourses -1:wait cannot use;+1:can use //"thired":? struct sembuf buf[2] = { {left, -1, 0}, {right, -1, 0} }; //semop do wait or signal (p/v) //"first": the number of share memory pro //"second":the first point of struct //"third":the number of signal to complete semop(semid, buf, 2); } void free_2fork(int no) { int left = no; int right = (no + 1) % 5; //system defined struct //"first":the current number of pro //"second":resourses -1:wait cannot use;+1:can use //"thired":? struct sembuf buf[2] = { {left, 1, 0}, {right, 1, 0} }; semop(semid, buf, 2); } void philosopere(int num) { srand(getpid()); for (; ;) { //printf("\033[31m Hello\n\033[0m"); //printf("\033[36m Hello\n\033[0m"); //printf("\%d is thinking\n", num); printf("\033[31m%d is thinking\n\033[0m", num); sleep(DELAY); printf("%d pick up two chopsticks\n", num); printf("\033[36m%d pick up two chopsticks\n\033[0m", num); wait_for_2fork(num); //printf("%d is eating\n", num); printf("\033[34m%d is eating\n\033[0m", num); sleep(DELAY); free_2fork(num); } } int main() { //use IPC to connect between processes . A new share memory //semget() return the number of share memory //new signal key=0 and never change .So not use key //"first":use IPC_PRIVATE to share memory between relation processes //"second":(size_t)naxSize //"third":(int flag)private:666--read and write ; IPC_CREAT creat new memory semid = semget(IPC_PRIVATE, 5, IPC_CREAT | 0666); if (semid == -1) ERR_EXIT("semget"); union semun su; su.val = 1; for (int i = 0; i < 5; i++) { //creat a new object on "semid" //use i to depart 5 processes semctl(semid, i, SETVAL, su); } int no = 0; //pid_t (Process ID _ Type) Just like int pid_t pid; for (int i = 1; i < 5; i++) { //use fork() to make a copy of father process named with child pro //father.pid>0 and child.pid=0 //after for loop will exist a father and five childs(0-4) pid = fork(); if (pid == -1) ERR_EXIT("fork"); if (pid == 0) { no = i; //break the child process loop to run the philosopere break; } } philosopere(no); return 0; }