#include <sys/types.h>
#include <sys/sem.h>
#include <ctype.h>
#include <sys/ipc.h>
#include <sys/stat.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
union semun {
int val;
struct semid_ds *buf;
unsigned short *array;
struct seminfo *__buf;
};
int main(int argc, char *argv[]) {
pid_t childPid;
int semid, j;
union semun arg;
struct semid_ds ds;
struct sembuf sops_p[1];
struct sembuf sops_c[1];
union semun dummy;
// 创建含一个信号量的信号量集
if((semid = semget(IPC_PRIVATE, 1, S_IRUSR | S_IWUSR)) == -1) {
printf("fail to semget\n");
exit(-1);
}
printf("semid = %d\n", semid); // 信号量集标识符
arg.buf = &ds;
if ((semctl(semid, 0, IPC_STAT, arg)) == -1) {
printf("fail to semctl IPC_STAT\n");
exit(-1);
}
if(ds.sem_nsems != 1) {
printf("semid %d contains %d sems, not 1\n", semid, ds.sem_nsems);
exit(-1);
}
arg.array = calloc(ds.sem_nsems, sizeof(arg.array[0]));
if(arg.array == NULL) {
printf("fail to calloc arg.array\n");
exit(-1);
}
for(j = 0;j < ds.sem_nsems;j++)
arg.array[j] = 0;
// 设置信号量初始值为0
if ((semctl(semid, 0, SETALL, arg)) == -1) {
printf("fail to semctl SETALL\n");
exit(-1);
}
// 创建子进程
switch (childPid = fork())
{
case -1:
printf("fail to fork\n");
exit(-1);
case 0:
printf("child start and doing some work\n");
sleep(5); // 模拟子进程执行消耗时间
printf("child finish work\n");
sops_c[0].sem_num = 0;
sops_c[0].sem_op = 1;
sops_c[0].sem_flg = 0;
// 子进程对信号量+1
if((semop(semid, sops_c, 1)) == -1) {
printf("child fail to semop\n");
exit(-1);
}
return 0;
default:
printf("parent wait...\n");
sops_p[0].sem_num = 0;
sops_p[0].sem_op = -1;
sops_p[0].sem_flg = 0;
// 父进程对信号量-1
// 初始由于信号量为0,该操作将阻塞,直到子进程将信号量+1
if((semop(semid, sops_p, 1)) == -1) {
printf("parent fail to semop\n");
exit(-1);
}
printf("parent finish\n");
// 删除信号量集
if((semctl(semid, 0, IPC_RMID, dummy)) == -1) {
printf("fail to semctl IPC_RMID\n");
exit(-1);
}
return 0;
}
}
利用SystemV信号量进行进程同步
最新推荐文章于 2024-07-09 17:58:15 发布