信号量集
2015-05-16 01:26:38 最后更新: 2015-08-12 18:13:09 访问数量:2378
2015-05-16 01:26:38 最后更新: 2015-08-12 18:13:09 访问数量:2378
信号量与其他的 IPC (管道、FIFO、消息队列、域套接字)都有所不同,他是一个计数器,用于多进程对共享数据对象的访问
当进程需要获得共享资源时,需要进行下列操作:
当然了,对信号量的测试及减 1 的操作必须是原子操作,因此,通常信号量是内核实现的
最常用的信号量初始值为 1,被称为“二元信号量”或“双态信号量”,控制单个资源,但是一般而言,信号量的初始值可以为任意正数,用来说明有多少个共享资源单位可供共享应用
XSI 的信号量集要比信号量复杂一些:
内核为每个信号量集设置了一个 semid_ds 结构:
各系统的具体实现会包含额外的字段
每个信号量由一个无名结构表示,至少包含下列成员:
定义于 sys/sem.h 中
调用成功返回信号量集 ID,否则返回 -1
该函数将 key 变换为信号量集标识符,并返回,与消息队列创建函数 msgget 一样:
参数 nsems 用于初始化该信号量集描述结构的 sem_nsems 字段
semctl 函数可以执行多种操作,与 ioctl、semctl、shmctl 非常类似,都被称为“垃圾桶函数”
定义于 sys/sem.h 中
根据 cmd 参数的不同,返回值有所不同
第四个参数 arg 是一个联合体 semun 类型的参数,根据 cmd 参数取值的不同而可选
参数 cmd 决定了 semctl 函数的用途、arg 参数的实际类型与函数的返回值
cmd 参数是下列 10 种命令中的一种:
取值 | 意义 |
IPC_STAT | 将 semid 指定的信号量集的 semid_ds 结构存放到 arg.buf 指向的结构中 |
IPC_SET | 按照 arg.buf 指向的结构中的值设置 semid 指定的信号量集的 semid_ds 结构(可以改变 sem_perm.uid、sem_perm.gid、sem_perm.mode),执行此命令的进程有效用户 ID 必须等于 sem_perm.cuid 或 sem_perm.uid 或者该进程具有超级用户权限 |
IPC_RMID | 从系统中删除该信号量集,信号量集会被立即删除,仍在使用次信号量集的其他进程对该信号量集的下次操作会返回 EIDRM,执行此命令的进程有效用户 ID 必须等于 sem_perm.cuid 或 sem_perm.uid 或者该进程具有超级用户权限 |
GETVAL | 返回信号量集成员 semnum 的 semval 值 |
SETVAL | 将信号量集成员 semnum 的 semval 值设定为 arg.val |
GETPID | 返回信号量集成员 semnum 的 sempid 值 |
GETNCNT | 返回信号量集成员 semnum 的 semncnt 值 |
GETZCNT | 返回信号量集成员 semnum 的 semzcnt 值 |
GETALL | 将信号量集中所有信号量的值存放到 arg.array 指向的数组中 |
SETALL | 将信号量集设定为 arg.array 数组存储数值信号量的集合 |
函数 semop 执行信号量集上的操作,即本文开头处图片中的过程,是一个原子操作
定义于 sys/sem.h
调用成功返回 0,否则返回 -1
参数 semoparray 是一个信号量操作数组,标识对每个信号量的操作
对集合中成员的具体操作由 semoparray 中存储的元素的 sem_op 字段指定
上述操作是原子性的
欢迎关注微信公众号,以技术为主,涉及历史、人文等多领域的学习与感悟,每周三到七篇推文,只有全部原创,只有干货没有鸡汤