这里记录一下我学习 Linux 信号量时我所理解的信号量 API 基本用法。很多内容来自手册,
如果有不清楚不详细的地方,可以参照手册理解。
struct semid_ds
1 | struct semid_ds { |
每个信号量集在内核里都有一个这样的数据结构。可以通过semctl()
函数获取,最后的例
子中有展示。
semget()
函数
1 |
|
函数semget()
用来获取一个信号量集的标识符,参数key
可以是IPC_PRIVATE
或者是由
函数ftok()
得到的一个 key。参数nsems
在新建信号量集时用来指定信号量集中的信号
量的数量,可以根据需要自己指定。参数semflg
可以指定IPC_CREAT
用来表示在key
所
绑定的信号量集不存在时创建一个新的,semflg
的最低 9 个比特用来表示新建信号量集
的权限,可以与其他参数直接相与来设置。
semget()
并不创建单个的信号量,而是创建一个集合,这个集合中包含多个信号量,所以
称作信号量集。
semop()
函数
1 |
|
参数semid
用来指定信号量集,参数sops
是一个指向struct sembuf
的指针,而实际上
这个一个数组的首地址,参数nsops
指针指向的一共有多少个项,struct sembuf
的定义
如下:
1 | struct sembuf { |
这个数组中的每个结构体定义了要对信号量进行的一个操作。sem_num
用来指定对信号量
集中的第几个信号量进行操作,sem_op
指定要进行的操作(即增加或减少信号量的值,给
定相应的正数或负数即可),sem_flg
可以设置的值有IPC_NOWAIT
和SEM_UNDO
,如果
指定了SEM_UNDO
则在进程结束后操作会被 undo。内核中每一个信号量集都保存的有一个
undo 表。
semctl()
函数
1 |
|
函数semctl()
会根据参数cmd
来对semid
所指定的信号量集进行操作,semnum
指定了
信号量集中的第几个信号量。函数根据参数cmd
的不同而可能有3个或4个参数,当有第4
个参数时,它的类型为union semun
,调用者必须把它定义为如下的形式:
1 | union semun { |
cmd
可能取的值为IPC_STAT
IPC_SET
IPC_RMID
GETVAL
SETVAL
等。下面是一个
小的例子程序:
1 |
|
注意
信号量集在程序退出后不会自动消失,需要使用函数semctl()
手动删除,或者使用命令ipcs -s
查看,使用命令ipcrm -s <semid>
删除。