信号量集结构:
struct semid_ds {
struct ipc_perm sem_perm; /* Ownership and permissions */
time_t sem_otime; /* Last semop time */
time_t sem_ctime; /* Last change time */
unsigned short sem_nsems; /* No. of semaphores in set */
};
信号量集函数:
#include<sys/types.h>
#include<sys/ipc.h>
#include<sys/sem.h>
int semget(key_t key, int nsems, int semflg);
int semctl(int semid, int semnum, int cmd, ...);
int semop(int semid, struct sembuf *sops, unsigned nsops);
semget函数:
功能:用来创建和访问一个信号量集
原型
int semget(key_t key, int nsems, int semflg);
参数
key:信号集的名字
nsems:信号集中信号量的个数
semflg:由九个权限标志构成,它们的用法和创建文件时使用的mode模式标志是一样的
返回值:成功返回一个非负整数,即该信号集的标识码;失败返回-1
semclt函数:
功能:用于控制信号量集
原型
int semctl(int semid, int semnum, int cmd, ...);
参数
semid:由semget返回的信号集标识码
semnum:信号集中信号量的序号
cmd:将要采取的动作(有五个可取值)
最后一个参数是 unionsemun,具体成员根据cmd 的不同而不同
unionsemun {
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) */
};
返回值:成功返回0;失败返回-1
cmd取值如下:
命令 | 说明 |
SETVAL | 设置信号量集中的信号量的计数值 |
GETVAL | 获取信号量集中的信号量的计数值 |
IPC_STAT | 把semid_ds结构中的数据设置为信号集的当前关联值 |
IPC_SET | 在进程有足够权限的前提下,把信号集的当前关联值设置为semid_ds数据结构中给出的值 |
IPC_RMID | 删除信号集 |
semop函数:
功能:用来创建和访问一个信号量集
原型
int semop(int semid, struct sembuf *sops, unsigned nsops);
参数
semid:是该信号量的标识码,也就是semget函数的返回值
sops:是个指向一个结构数值的指针
nsops:信号量的个数
返回值:成功返回0;失败返回-1
sembuf结构体:
struct sembuf {
short sem_num;
short sem_op;
short sem_flg;
};
sem_num是信号量的编号。
sem_op是信号量一次PV操作时加减的数值,一般只会用到两个值,一个是“-1”,也就是P操作,等待信号量变得可用;另一个是“+1”,也就是我们的V操作,发出信号量已经变得可用
sem_flag的两个取值是IPC_NOWAIT或SEM_UNDO
sem_op:是信号量一次PV操作时加减的数值,一般只会用到两个值,一个是“-1”,也就是P操作,等待信号量变得可用;另一个是“+1”,也就是我们的V操作,发出信号量已经变得可用。当然+-n 和0 都是允许的。需要注意的是只有+n 才确保将semval +n 后马上返回,而-n 和 0 很可能是会阻塞的,+-n需要进程对信号集有写的权限,而0只需要读的权限。
sem_flag:的两个取值是IPC_NOWAIT或SEM_UNDO,设为前者如果当某个信号量的资源为0时进行P操作,此时不会阻塞等待,而是直接返回资源不可用的错误;设为后者,当退出进程时对信号量资源的操作撤销;不关心时设置为0即可。
当要对一个信号量集中的多个信号量进行操作时,sops是结构体数组的指针,此时nsops不为1。此时对多个信号量的操作是作为一个单元原子操作,要么全部执行,要么全部不执行。