實現代碼
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <sys/wait.h>
static int set_semvalue(void);
static int semaphore_p(void);
static int semaphore_v(void);
static void del_sem_set(void);
/* 定義自己的semun聯合體*/
union semun {
int val;
struct semid_ds *buf;
unsigned short *array;
struct seminfo *__buf;
};
/* 定義全局變量sem_id保存信號量集的標識符*/
static int sem_id;
int main()
{
int i;
pid_t pid;
char ch;
/* 創建信號量集*/
sem_id = semget(IPC_PRIVATE, 1, 0666 | IPC_CREAT);
if(sem_id == -1) {
fprintf(stderr, "Failed to create semaphore set. \n");
exit(EXIT_FAILURE);
}
if(!set_semvalue()) { /* 設置信號量的值*/
fprintf(stderr, "Failed to initialize semaphore\n");
exit(EXIT_FAILURE);
}
pid = fork(); /* 創建子進程*/
switch(pid)
{
case -1:
perror("fork failed");
exit(EXIT_FAILURE);
case 0: /* 子進程*/
ch = 'c';
break;
default: /* 父進程*/
ch = 'p';
break;
}
for(i=0; i < 5; i++){ /* 使用信號量控制*/
// semaphore_p(); /* P操作,獲取信號量*/
printf("%c", ch); /* 在父進程中輸出X,在子進程中輸出O */
fflush(stdout);
sleep(1);
// semaphore_v(); /* V操作,釋放信號量*/
}
if(pid > 0) { /* 父進程*/
wait(NULL); /* 等待子進程退出*/
del_sem_set(); /* 刪除信號量集*/
}
printf("PID%d - finished", getpid());
exit(EXIT_SUCCESS);
}
/* 設置信號量的值*/
static int set_semvalue(void)
{
union semun sem_union;
sem_union.val = 1;
if(semctl(sem_id, 0, SETVAL, sem_union) == -1)
return 0;
return 1;
}
/* P操作,獲取信號量*/
static int semaphore_p(void)
{
struct sembuf sem_b;
sem_b.sem_num = 0;
sem_b.sem_op = -1;
sem_b.sem_flg = SEM_UNDO;
if(semop(sem_id, &sem_b, 1) == -1) {
fprintf(stderr, "semaphore_p failed/n");
return 0;
}
return 1;
}
/* V操作,釋放信號量*/
static int semaphore_v(void)
{
struct sembuf sem_b;
sem_b.sem_num = 0;
sem_b.sem_op = 1;
sem_b.sem_flg = SEM_UNDO;
if(semop(sem_id, &sem_b, 1) == -1) {
fprintf(stderr, "semaphore_v failed/n");
return 0;
}
return 1;
}
/* 刪除信號量集*/
static void del_sem_set(void)
{
union semun sem_union;
if(semctl(sem_id, 0, IPC_RMID, sem_union) == -1)
fprintf(stderr, "Failed to delete semaphore/n");
}
運行結果
pcpcpcpcpc
PID15974 - finished
PID15973 - finished
分析:因爲在進程調用的主函數中相關程序段使用了信號量控制,所以在程序執行過程中各進程對這一程序段是互斥訪問的,一個進程執行完後另一個進程開始執行。
修改程序
在主程序中註釋掉“semaphore_p()”和“semaphore_v()”兩處語句,觀察實驗結果。
for(i=0; i < 5; i++){ /* 使用信號量控制*/
// semaphore_p(); /* P操作,獲取信號量*/
printf("%c", ch); /* 在父進程中輸出X,在子進程中輸出O */
fflush(stdout);
sleep(1);
// semaphore_v(); /* V操作,釋放信號量*/
}
運行結果
pccppcpccp
PID16071 - finished
PID16070 - finished
分析:沒有使用信號量控制,循環打印語句的執行結果不確定。