SystemV IPC 方案的相关内容都是通过 “房间密码”来创建房间,获取到房间的ID,后面其他进程也可以根据这个房间密码来拿到同一个房间的ID。这是理解下面这些操作函数的关键。
目录
1、信号量集合的创建 semget
2、信号量的初始化 / 销毁 semctl
3、信号量的PV操作 semop
1、信号量集合的创建 semget
注意这里是信号量集合的创建,semget 可以一次创建多个信号量,为了管理这些信号量,统一把这些信号量放在一个信号量集合中,如果创建成功,返回的就是信号集的ID。
第一个参数 key:“房间密码”。通过ftok函数获取,。
第二个参数 nsem:信号量集合中信号量的个数。如果不打算创建 一个新的信号量集合的时候,该参数可以是0。
第三个参数 semflg:信号量集合的访问权限。通常是IPC_CREAT | 0666,如果信号量集合已经存在,那么信号量集合的访问权限会被修改成当前填入的权限。
返回值:成功返回信号量集合的ID,失败返回 -1
key_t key = ftok(".", 100);
// 创建一个信号量集合,该信号集包含2个信号量,访问权限为 0666
semget(key, 2, IPC_CREAT | 0666);
2、信号量的初始化 / 销毁 semctl
semctl 可以对信号量集合中的信号量进行初始化或者删除。因为现在只有信号量集合的ID,实际上我们要想操作信号量集合中的某一个信号量,需要先给这些信号量编号,然后根据编号来定向操作某一个信号量。
第一个参数 semid:信号量集合的ID
第二个参数 semnum:要操作信号量集合中的信号量编号。信号量集合给信号量编号的方式类似于数组下标,是从0开始的,所以为了区分哪个信号量是干什么用的,可以使用宏或者 枚举的方式来指明。
// 枚举的方式
// SEM_WR: 对应下标0
// SEM_RD: 对应下标1
enum SEM
{
SEM_WR,
SEM_RD
};
// 宏定义的方式
#define SEM_WR 0
#define SEM_RD 1
第三个参数 cmd:要对信号量所作的操作。可选值如下:
可选值 | 含义 |
GETVAL | 获取第 semnum 个信号量的值,当前函数的返回值就是获得值。 |
SETVAL | 设置信号量的值,需要用到第四个参数联合体 |
IPC_RMID | 删除当前信号量集合 |
第四个参数:根据不同的cmd,可能需要传递参数。比如,当cmd=SETVAL时,需要填入第四个参数来告知当前函数,你想要要设置的值。第四个参数是一个联合体,联合体的格式如下:
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) */
};
返回值:失败返回 -1;成功时会根据cmd的值返回不同的值(值是大于0的)
3、信号量的PV操作 semop
semop包含了对信号量集合中信号量的 P操作(申请) 和 V操作(释放)。
第一个参数 semid:信号量集合的ID
第二个参数 sops:输入型参数,要对信号量集合中的哪个信号量做什么操作,阻塞方式又是怎样。结构体sembuf 的声明如下:
struct sembuf {
unsigned short sem_num; // 要操作的信号量的编号
short sem_op; // 对信号量进行的操作
// 1: 释放资源,V操作
// -1: 申请资源,P操作
short sem_flg; // 阻塞方式。0表示阻塞,IPC_NOWAIT表示非阻塞
};
注意:如果要一次操作多个信号量,那么就需要定义一个sembuf类型的结构体数组
第三个参数 nsops:要操作的信号量的个数。一般是 1
返回值:成功返回 0,失败返回 -1。