标签:
内核为每个信号量集合设置了一个semid_ds结构
struct semid_ds { struct ipc_permsem_perm ; structsem* sem_base ; //信号数组指针 ushort sem_nsem ; //此集中信号个数 time_t sem_otime ; //最后一次semop时间 time_t sem_ctime ; //最后一次创建时间 } ; 每个信号量由一个无名结构表示,它至少包含下列成员: (这个是什么意思??) struct { ushort_t semval ; //信号量的值 short sempid ; //最后一个调用semop的进程ID ushort semncnt ; //等待该信号量值大于当前值的进程数(一有进程释放资源 就被唤醒) ushort semzcnt ; //等待该信号量值等于0的进程数 } ;
#include <sys/sem.h>
int semget (key_t key, int nsem, int oflag) ;
#include <sys/sem.h>
int semop (int semid, struct sembuf * opsptr, size_t nops) ;
参数opsptr是一个指针,它指向一个信号量操作数组,信号量操作由sembuf结构表示:
struct sembuf{ short sem_num; // 除非使用一组信号量,否则它为0 short sem_op; // 信号量在一次操作中需要改变的数据,通常是两个数, // 一个是-1,即P(等待)操作,一个是+1,即V(发送信号)操作 short sem_flg; // 通常为SEM_UNDO,使操作系统跟踪信号,并在进程没有释放该信号量而终止时, // 操作系统释放信号量 };
#include <sys/sem.h>
int semctl (int semid, int semnum, int cmd, /*可选参数*/ ) ;
semget并不初始化各个信号量的值,这个初始化必须通过以SETVAL命令(设置集合中的一个值)或SETALL命令(设置集合中的所有值) 调用semctl来完成。
SystemV信号量的设计中,创建一个信号量集并将它初始化需两次函数调用是一个致命的缺陷。一个不完备的解决方案是:在调用semget时指定IPC_CREAT | IPC_EXCL标志,这样只有一个进程(首先调用semget的那个进程)创建所需信号量,该进程随后初始化该信号量。
SEM_UNDO
当操作信号量(semop)时,sem_flg可以设置SEM_UNDO标识;SEM_UNDO用于将修改的信号量值在进程正常退出(调用exit退出或main执行完)或异常退出(如段异常、除0异常、收到KILL信号等)时归还给信号量。
如信号量初始值是20,进程以SEM_UNDO方式操作信号量减2,减5,加1;在进程未退出时,信号量变成20-2-5+1=14;在进程退出时,将修改的值归还给信号量,信号量变成14+2+5-1=20。
标签:
原文地址:http://www.cnblogs.com/guochuanrui/p/5677570.html