一、什么是信号量?
信号量(semaphore)与已经介绍过的 IPC 结构不同,它是一个计数器。信号量用于实现进程间的互斥与同步,而不是用于存储进程间通信数据。
二、常用API
1.semget()函数
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
//创建或获取一个信号量组
int semget(key_t key, int nsems, int semflg);
参数:
key_t key: 一个key值
int nsems: 信号量的个数
int semflg: 获取信号量的权限,如果没有就创建一个信号量
返回值:若成功返回信号量集ID,失败返回-1
2.semop()函数
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
//完成对信号量的P操作或V操作
int semop(int semid, struct sembuf *sops, unsigned nsops);
参数:
int semid: 信号量的id值
struct sembuf *sops: PV操作的具体内容结构体
unsigned nsops: 操作结构的数量,大于或等于1
返回值:成功返回0。错误返回-1,errno表示错误
3.semctl()函数
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
//控制信号量的信息:删除信号量或初始化信号量
int semctl(int semid, int semnum, int cmd, ...);
参数:
int semid: 要操作信号量的id
int semnum: 要操作第几个信号量
int cmd: 默认写SETVAL,设置信号量的值
三、编程示例
信号量拿钥匙、取钥匙代码实战
#include <stdio.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
union semun {
int val; /* Value for SETVAL */
struct semid_ds *buf; /* Buffer for IPC_STAT, IPC_SET */
unsigned short *array; /* Array for GETALL, SETALL */
struct seminfo *__buf; /* Buffer for IPC_INFO
(Linux-specific) */
};
void pGetKey(int id)//取钥匙
{
struct sembuf set;
set.sem_num = 0;// //信号量的编号,默认是0
set.sem_op = -1;
set.sem_flg = SEM_UNDO;
semop(id,&set,1);
printf("getkey\n");
}
void vPutBackKey(int id)//放回钥匙
{
struct sembuf set;
set.sem_num = 0;
set.sem_op = 1;
set.sem_flg = SEM_UNDO;
semop(id,&set,1);
printf("put back the key\n");
}
int main(int argc,char const *argv[])
{
key_t key;
int semid;
key = ftok(".",2);
//信号量集合中有一个信号量
semid = semget(key,1,IPC_CREAT|0666);//获取/创建信号量
union semun initsem;
initsem.val = 0;
//操作第1个信号量
semctl(semid,0,SETVAL,initsem);//初始化信号量
int pid = fork();
if(pid > 0){
pGetKey(semid); //去拿钥匙
printf("this is father\n");
vPutBackKey(semid);//钥匙放回去
semctl(semid,0,IPC_RMID);//销毁钥匙
}else if(pid == 0){
printf("this is child\n");
vPutBackKey(semid);//钥匙放回去
}else{
printf("fork error\n");
}
return 0;
}