说到底,信号量就是用来控制多个进程对共享资源使用的一个计数器
相关数据结构1、sem
信号量对象是多个信号量的集合,而这个集合在linux中是以数组的形式实现的,数组的每个成员都是一个单独的信号量,即sem结构
- struct
- {
- short sempid; /*最近一次操作信号量的进程的id*/
- unsigned short semval; /*信号量的计数值*/
- unsigned short semncnt; /*等待使用资源的进程数目*/
- unsigned short semzcnt; /*等待资源完全空闲的进程数目*/
- }
2、semun
- 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 */
- void *__pad;
- };
3、sembuf
被用来定义对信号量对象的基本操作。
- struct sembuf
- {
- unsigned short sem_num; /* 接受操作的信号量在信号量数组中的序号,即数组下标 */
- short sem_op; /* 定义了进行的操作,取值正、0和负值 */
- short sem_flg; /* 控制操作行为的标志 */
- };
3.1 如果sem_op值为负,就从指定的信号量中减去相应的值,对应着获取信号量所监控的资源的操作。若sem_flg中没有指定IPC_NOWAIT标志,如果现有的信号量数值小于sem_op的绝对值(表示现有资源少于所需资源),调用semop()的进程就会阻塞直到信号量的数值大于sem_op的绝对值(表示有足够的资源)。
3.2 如果sem_op值为正,就在指定的信号量中加上相应的值,这对应着释放信号量所监控的资源的操作。
3.3 如果sem_op值为零,调用semop()的进程会被阻塞直到对应的信号量值为0。这操作就是等待信号量所监控的资源被全部使用。利用这个操作可以动态监控资源的使用并调整资源的分配,避免不必要的等待。
4、semid_ds
- struct semid_ds
- {
- struct ipc_perm sem_perm; /* permissions .. see ipc.h */
- __kernel_time_t sem_otime; /* 最近一次semop操作的时间 */
- __kernel_time_t sem_ctime; /* 信号量对象最近一次改动发生的时间 */
- struct sem *sem_base; /* 信号里数组的起始地址 */
- struct sem_queue *sem_pending; /* 指向还未进行的操作 */
- struct sem_queue **sem_pending_last; /* 指向最后一个还未进行的操作 */
- struct sem_undo *undo; /* undo requests on this array */
- unsigned short sem_nsems; /* 信号量数组成员数目 */
- };
和msqid_ds类似,semid_ds用来储存每个信号量对象的有关信息。
相关函数1、semget()
- #include <sys/types.h>
- #include <sys/ipc.h>
- #include <sys/sem.h>
- int semget(key_t key, int nsems, int semflg);
semget建立新的信号量对象或者获取已有对象的标识符。参数semflg与消息队列中的msgflg参数取值一样,详见
http://blog.chinaunix.net/uid-12845622-id-3258301.html;参数nsems是信息量对象中信号量的数目,也就是信号量数组成员的个数。/usr/include/linux/sem.h中定义了它的上限,#define SEMMSL 250
2、semop()
- #include <sys/types.h>
- #include <sys/ipc.h>
- #include <sys/sem.h>
- int semop(int semid, struct sembuf *sops, unsigned nsops);
semop()用来改变信号量对象中各个信号量的状态。参数sops是sembuf类型的数组,定义了semop()函数所要进行的操作序列;参数nsops是sops数组的长度也就是semop()进行的操作个数。
3、semctl()
- #include <sys/types.h>
- #include <sys/ipc.h>
- #include <sys/sem.h>
- int semctl(int semid, int semnum, int cmd, ...);
semctl()直接来控制信号量对象。semid为信号量对象标识符,semnum信号量在集合中的序号。根据cmd的取值,可带第4个参数,union semun arg。cmd可取如下值
IPC_STAT: 取得semid的semid_ds信息,并存放在arg的buf中
IPC_SET : 用arg中的buf设定信号量对象的semid_ds结构
IPC_RMID: 删除信号量对象
GETALL : 取得信号量对象所有信号量的值,并存放在arg的array中返回
GETNCNT : 返回正在等待使用某个信号量所控制的资源的进程数目
GETPID : 返回最近一个对某个信号量调用semop()的进程的pid
GETVAL : 返回集合中最后一个信号量的semval值
GETZCNT : 返回正在等待某个信号量所控制资源被全部使用的进程数目
SETALL :用arg中array来设定对象内处个信号量的值
SETVAL : 用arg中val的值来设定对象中某个信号量的值
阅读(2252) | 评论(0) | 转发(0) |