理解主要有4点:
1,信号量其实是一个计数变量,它只能为正整数和0,为0时表示该信号量对应的可用资源数为0;
2,semget可以创建多个信号量,而对应的semid所以称为信号量集的id;
#define SEM_KEY 0x11223344
#define NUM_SEM 2
//创建了一个包含2个信号量的信号量集,两个信号量的索引号是0和1
semid=semget(SEM_KEY,NUM_SEM,IPC_CREAT|IPC_EXCL|0666);
3,semop可以一次性进行多个操作,多个操作可以针对同一信号量,也可针对不同信号量,取决于struct sembuf的设置;
struct sembuf sem[2];
sem[0].sem_num = 0;/*对索引号为0的信号量进行操作*/
sem[1].sem_num = 0;/*对索引号为0的信号量进行操作*/
sem[0].sem_op = 0;
sem[1].sem_op = 1;
semop(semid,sem,2); /*最后一个参数nsops=2,所以在函数中同时执行执行sem[0],sem[1]两个操作,如果为1则执行sem[0]操作*/
4,sem_op数量的含义
信号量的 SysV 实现比上述解决方案更通用。首先,信号量的值不需要是 0 或 1;它可以是 0 或任何正数。其次,可以执行一系列信号量操作,与用于 msgrcv
的 type
参数非常类似。这些操作作为一个指令集提供给内核,并且这些指令要么全部运行,要么一个也不会运行。内核要求将这些指令放在一个名为 sembuf
的结构中,该结构具有以下成员(按顺序):
-
sem_num
:描述正在操作该集合中的哪一个信号量。 -
sem_op
:一个有符号整数,其中包含要执行的指令或测试。 -
sem_flg
:熟悉的IPC_NOWAIT
标志(它指示测试应该立即返回还是阻塞直至通过)和SEM_UNDO
(它在进程提前退出时导致撤销该信号量操作)的组合。
sem_op
是放置许多配置的地方:
- 如果
sem_op
为 0,则测试sem_num
以确定它是否为 0。如果sem_num
为 0,则运行下一个测试。如果sem_num
不为 0,则在未设置IPC_NOWAIT
时,操作将阻塞直至信号量变为 0,而在设置了IPC_NOWAIT
时,则跳过其他测试。 - 如果
sem_op
是某个正数,则将信号量的值加上sem_op
的值。 - 如果
sem_op
是一个负整数,并且信号量的值大于或等于sem_op
的绝对值,则从信号量的值减去该绝对值。 - 如果
sem_op
是一个负整数,并且信号量的值小于sem_op
的绝对值,则在IPC_NOWAIT
为 true 时立即停止测试的执行,而在该值为 false 时则阻塞,直至信号量的值变得大于sem_op
的绝对值。