[linux系统编程]System V IPC 信号量做进程间互斥

时间:2022-07-30 14:48:10
static int sem_id;
int lock_db()
{
struct sembuf sops;
sops.sem_num = 0; //操作第一个信号量
sops.sem_op = -1; //对该信号量操作-1
sops.sem_flg = SEM_UNDO;
//sops.sem_flg = 0;

return semop(sem_id, (struct sembuf *)&sops, 1);
}

int unlock_db()
{
struct sembuf sops;

sops.sem_num = 0; //操作第一个信号量
sops.sem_op = 1; //对该信号量操作+1
sops.sem_flg = SEM_UNDO; //IPC_NOWAIT :对信号的操作不能满足时,semop()不会阻塞,并立即返回,同时设定错误信息
//SEM_UNDO :程序结束时(不论正常或不正常),保证信号值会被重设为semop()调用前的值。这样做的目的在于避免程序在异常情况下结束时未将锁定的资源解锁,造成该资源永远锁定。
//sops.sem_flg = 0;

return semop(sem_id, (struct sembuf *)&sops, 1);
}

int main()
{
int ret;
unsigned short sem_array[2];
union semun
{
int val;
struct semid_ds *buf;
unsigned short *array;
}arg;
sem_id = semget((key_t)123456, 2, IPC_CREAT | 0644); //创建或获取键值为123456的信号量集标识,该信号量集中有两个信号量
sem_array[0] = 1; //第一个信号量用来做互斥
sem_array[1] = 201; //第二个信号量用来标识初始化
arg.array = sem_array;

if(semctl(sem_id, 1, GETVAL) != 201) //返回信号量集中的第二个信号量的值(第一个信号量编号是0),判断是否初始化第一个信号量
{
ret = semctl(sem_id, 0, SETALL, arg); //设置信号量的值
if(ret == -1)
{
printf("SETALL failed (%d)\n", errno);
exit(1);
}
}
return 0;
}


System V信号量的操作接口:
创建和打开信号量:
        int semget(key_t key, int nsems, int oflag);
        
设置信号量的值(PV操作):
        int semop(int semid, struct sembuf *opsptr, size_t nops);
        
控制操作信号量集:
        int semctl(int semid, int semum, int cmd, .../*union semun arg*/);