Linux 訊號量同步實驗
阿新 • • 發佈:2019-01-31
題目:有一個盤子,父親放入蘋果,母親放入桔子,女兒取出蘋果,兒子取出桔子。
同步關係:父親放蘋果和女兒取蘋果 && 母親放桔子和兒子取桔子
互斥關係:父親放蘋果和母親放桔子
下面是原始碼:
#include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <sys/types.h> #include <sys/sem.h> #include <sys/shm.h> #include <errno.h> union semun { int val; struct semid_ds *buf; unsigned short *array; }; int main(int argc, char *argv[]) { struct sembuf P, V; union semun arg; if (argc != 3) { //命令列引數個數必須為3 printf("usage: ./sem <APPLE> <ORANGE>\n"); exit(1); } int APPLE = atoi(argv[1]); //父親放入的蘋果數 int ORANGE = atoi(argv[2]); //母親放入的桔子數 int getappleid = shmget(IPC_PRIVATE, sizeof(int), IPC_CREAT|0666); //申請共享記憶體 int getorangeid = shmget(IPC_PRIVATE, sizeof(int), IPC_CREAT|0666); int *getapple = (int*) shmat(getappleid, 0, 0); //繫結共享記憶體 int *getorange = (int*) shmat(getorangeid, 0, 0); *getapple = 0; //初始化取出蘋果數為0 *getorange = 0; //初始化取出桔子數為0 int empty = semget(IPC_PRIVATE, 1, IPC_CREAT|0666); //盤子是否為空的訊號量 int apple = semget(IPC_PRIVATE, 1, IPC_CREAT|0666); //盤子中是否有蘋果的訊號量 int orange = semget(IPC_PRIVATE, 1, IPC_CREAT|0666); //盤子中是否有桔子的訊號量 int mutex = semget(IPC_PRIVATE, 1, IPC_CREAT|0666); //放入盤子和取出盤子的互斥訊號量 arg.val = 1; if (semctl(empty, 0, SETVAL, arg) == -1) //設定訊號量 perror("semctl setval error"); arg.val = 0; if (semctl(apple, 0, SETVAL ,arg) == -1) perror("semctl setval error"); arg.val = 0; if (semctl(orange, 0, SETVAL, arg) == -1) perror("semctl setval error"); arg.val = 1; if (semctl(mutex, 0, SETVAL, arg) == -1) perror("semctl setval error"); P.sem_num = 0; //定義P、V操作 P.sem_op = -1; P.sem_flg = SEM_UNDO; V.sem_num = 0; V.sem_op = 1; V.sem_flg = SEM_UNDO; if (fork() == 0) { //父親程序 int i = 0; for (; i < APPLE; i++) { //迴圈放入蘋果 semop(empty, &P, 1); semop(mutex, &P, 1); printf("Father put APPLE\n"); semop(mutex, &V, 1); semop(apple, &V, 1); } sleep(2); printf("Father is over!\n"); exit(0); } else { if (fork() == 0) { //母親程序 int i = 0; for (; i < ORANGE; i++) { //迴圈放入桔子 semop(empty, &P, 1); semop(mutex, &P, 1); printf("Mother put ORANGE\n"); semop(mutex, &V, 1); semop(orange, &V, 1); sleep(1); } printf("Mother is over!\n"); exit(0); } else { if (fork() == 0) { //女兒程序 while (1) { //取出蘋果 if (*getapple == APPLE) break; semop(apple, &P, 1); semop(mutex, &P, 1); printf("\tDaughter get APPLE!\n\n"); (*getapple)++; semop(mutex, &V, 1); semop(empty, &V, 1); sleep(1); } printf("\tDaughter get all APPLE!\n\n"); exit(0); } else { if (fork() == 0) { //兒子程序 while (1) { //取出桔子 if (*getorange == ORANGE) break; semop(orange, &P, 1); semop(mutex, &P, 1); printf("\tSon get ORANGE!\n\n"); (*getorange)++; semop(mutex, &V, 1); semop(empty, &V, 1); sleep(1); } printf("\tSon get all ORANGE!\n\n"); exit(0); } } } } wait(0); //等待子程序結束 wait(0); wait(0); wait(0); printf("\nAll processor end!\n\n"); shmdt(getapple); //釋放共享記憶體 shmctl(getappleid, IPC_RMID, 0); shmdt(getorange); shmctl(getorangeid, IPC_RMID, 0); semctl(empty, IPC_RMID, 0); //釋放訊號量 semctl(apple, IPC_RMID, 0); semctl(orange, IPC_RMID, 0); semctl(mutex, IPC_RMID, 0); exit(0); }
上面的程式碼是最終能在所有Linux下執行的版本。之前因為標頭檔案是 linux/sem.h 和 linux/shm.h 導致無法在部分linux下執行。我看見Unix高階程式設計上面用的 sys/sem.h 和 sys/shm.h,並結合下面的文章對之前的程式碼進行了修改。