1. semget函数
semget函数的作用:创建一个新信号量或取得一个已有信号量的键。
int semget(key_t key,int num_sems,int sem_flags);
第一个参数key是整数值,不相关的进程可以通过它访问同一个信号量。程序对所有信号量的访问都是间接的,他先提供一个键,再由系统生成一个相应的信号量标识符。
只有semget函数才直接使用信号量键,所有其他的信号量函数都是使用由semget函数返回的信号量标识符。
第二个参数num_sems参数是指定需要的信号量数目。几乎总是取值为1.
第三个参数是一组标志,与open函数的标志非常相似。它低端的9个比特位是该信号量的权限,其作用类似于文件多的访问权限。此外,它们还可以和值IPC_CRAEAT做按位或操作,来创建一个新信号量。即使在设置了IPC_CREAT标志后给出的一个键是一个已有信号量的键,也不会产生错误。如果函数用不到IPC_CREAT标志,该标志就会悄悄的忽略掉。我们可以通过联合使用标志IPC_CREAT和IPC_ECXCL来确保创建出的是一个新的唯一的信号量。如果该信号量已经存在,它将返回一个错误。
IPC_PRIVATE是一个特殊的信号量键值,它的作用是创建一个只有创建者进程才可以访问的信号量,但这个键值很少由实际的用途。在创建新的信号量时,你需要给键提供一个唯一的非零整数。
semget函数在成功时返回一个正数值,它就是其他信号量函数将用到的信号量标识符。失败则返回-1.
2.semop函数
semop函数用于改变信号量的值,对信号量集中的一个或多个信号量进行p操作或v操作。
int semop(int sem_id,struct sembuf *sem_ops,size_t num_sem_ops);
其中第一个参数是由semget所返回的信号量标识符。
第二个参数sem_ops是指向一个结构数组的指针,每个数组元素至少包括以下几个成员:
struct sembuf {
short sem_num;//信号量编号,除非你需要使用一组信号量,否则他的取值一般为0
short sem_op;//信号量在一次操作中需要改变的数值(可以使用一个非1的数值来改变信号量的值)。通常只会用到两个值,一个是-1,即p操作,它等待信号量变为可用;一个是+1,即v操作,它发送信号信号表示信号量现在已可用
short sem_flg;//通常被设置为SEM_UNDO。这可以使得操作系统跟踪当前进程对这个信号量的修改情况,如果这个进程在没有释放该信号量的情况下终止,操作系统将自动释放该进程持有的信号量。如果一定使用一个非SEM_UNDO的值,那就要注意设置的一致性,否则会搞不清内核是否会在进程退出时清理信号量。
}
第三个参数:进行操作信号量的个数,即sembuf结构体变量的个数,需大于等于1.当设置等于1时,只完成对一个信号量的操作。
semop调用的一切动作都是一次性完成的,这是为了避免出现因使用多个信号量而可能发生的竞争现象。
3.semctl函数
该函数是用来直接控制信号量信息
int semctl(int sem_id,int sem_num,int command,...);
第一个参数是semget函数返回的信号量标识符。
第二个参数是信号量编号,当需要用到成组的信号量时(信号量集),就用到这个参数,相当于数组的下标,一般取值为0,表示这是第一个也是唯一一个的信号量。
第三个参数是将要采取的动作。command参数可以设置许多不同的值,其中有两种最常用的:
SETVAL:用来把信号量初始化为一个已知的值。这个值通过union semun 中的val成员设置。其作用是在信号量第一次使用之前对它进行设置。
IPC_RMID:删除一个已经无需继续使用的信号量标识符。
如果还有第四个参数,将会是一个union semun 结构,这个结构至少包括:
union semun{
int val;
struct semid_ds *buf;
unsigned short *array;
}