父子进程信号量

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
#include <sys/sem.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>

union semun { // 此结构体为semctl系统调用的第四个参数的推荐格式,由sys/sem.h给出
int val; // 用于SETVAL命令
struct semid_ds* buf; // 用于IPC_STAT和IPC_SET命令
unsigned short int* array; // 用于GETALL和SETALL命令
struct seminfo* __buf; // 用于IPC_INFO命令
};

void pv(int sem_id, int op) { // 此函数用于操作sem_id信号集的信号量,对其做出 +op 的操作
struct sembuf sem_b; // 每一个sembuf结构体都对应一个信号量操作
sem_b.sem_num = 0; // 信号集中信号量的编号,0表示信号集中第0个信号量
sem_b.sem_op = op;
sem_b.sem_flg = SEM_UNDO; // 该标志意思为,当进程退出时取消正在进行的semop操作
semop(sem_id, &sem_b, 1); // 失败时 数组内所有操作都不执行
}

int main(int argc, char* argv[]) {
int sem_id = semget(IPC_PRIVATE, 1, 0666); // 无论信号量是否已经存在,都会创建一个 新 的信号量。IPC_NEW这个名字更合适

union semun sem_un;
sem_un.val = 1;
semctl(sem_id, 0, SETVAL, sem_un); // 第0个信号,执行SETVAL命令,参数为sum_un

pid_t id = fork();
if (id < 0) {
return 1;
} else if (id == 0) { // 子进程
printf("child try to get binary sem\n");
pv(sem_id, -1);
printf("child get the sem and would release it after 5 seconds\n");
sleep(5);
pv(sem_id, 1);
exit(0);
} else { // 父进程
printf("parent try to get binary sem\n");
pv(sem_id, -1);
printf("parent get the sem and would release it after 5 seconds\n");
sleep(5);
pv(sem_id, 1);
}
waitpid(id, NULL, 0); // 父进程等待子进程结束
semctl(sem_id, 0, IPC_RMID, sem_un); // remove id 删除信号量
return 0;
}

在这里插入图片描述


reference: linux高性能服务器编程——游双