1 概述
计数信号量集semid_ds:
struct semid_ds { struct ipc_perm sem_perm; struct sem *sem_base; //指向信号量结构数组
unsigned short sem_nsems; //信号量集中信号量数目
time_t sem_otime; //last semop时间
time_t sem_ctime; };
sem结构是内核用于维护某个给定信号量的内部数据结构:
struct sem { unsigned short semval; //信号量值
pid_t sempid;
unsigned short semncnt; //等待信号量值增长到某个值的进程数
unsigned short semzcnt; //等待信号量值为0的进程数 };
2 semget函数
#include <sys/sem.h> int semget(key_t key,int nsems,int oflag)
key为IPC_PRIVATE或未与某个IPC对象相关联其oflag中指定IPC_CREAT,则创建信号量集
信号量集中信号量值并不进行初始化,需要通过SETVAL或SETALL命令调用semctl函数进行初始化
3 semop函数
semop函数对信号量集进行操作,增加或减小信号量值,对应释放与分配资源
int semop(int semid,struct sembuf *opsptr,size_t nops)
sembuf是针对信号集中的某个信号进行指定操作的结构,semop函数在信号集semid上进行nops个信号操作
struct sembuf { short sem_num; short sem_op; short sem_flg; };
sem_num:指定信号集中进行操作的信号
sem_op:大于0:进程释放sem_num信号量关联的资源,释放资源数为sem_op,将sem_op加到信号值中,同时从信号量调整值中减去sem_op
小于0:进程希望获取sem_num信号量关联的资源,占用数为|sem_op|,根据semval的值和sem_flg决定阻塞还是返回
等于0:进程希望等待信号量值变成0
sem_flg:IPC_NOWAIT:非阻塞
IPC_UNDO:是否开启信号量调整(占用资源的进程因临时终止没能调整信号量值的情况是存在的,为了避免,在分配或释放资源时,用信号量调整值记录进程占用的资源)
4 semctl函数
int semctl(int semid,int semnum,int cmd,/* union semun arg */)
semctl函数中cmt命令分为三种:针对信号量集本身,针对某个信号量,针对所有信号量
因此定义共用体semun,针对不同的cmd,对semun有不同的使用:
union semun { int val; //SETVAL struct semid_ds *buf; //IPC_STAT,IPC_SET unsigned short *array; //SETALL,GETALL };
针对信号量集:
IPC_STAT:取信号量集信息存于semun.buf中
IPC_SET:根据semun.buf设置信号量集的sem_perm.uid,sem_perm.gid
IPC_RMID:删除信号量集
针对特定信号量semnum:
GETVAL:返回信号量semval
SETVAL:根据semun.val设置信号量值
GETPID:返回信号量的sempid
GETNCNT:返回信号量的semncnt
GETZCNT:返回信号量的semzcnt
针对所有信号量:
GETALL:写所有信号量值到semun.array
SETALL:根据semun.array各元素值设置所有信号量值