使用System V和Posix信号量之间的权衡是什么?
来自O'Reilly:
- System V和POSIX信号量的一个显著区别在于,在System V中,您可以控制信号量计数增加或减少的数量;而在POSIX中,信号量计数增加或减少1。
- POSIX信号量不允许操纵信号量权限,而System V信号量允许您将信号量的权限更改为原始权限的子集。
- 在POSIX信号量中,初始化和创建信号量是原子的(从用户的角度来看)。
- 从使用的角度来看,System V信号量很笨拙,而POSIX信号量很直观。
- POSIX信号量的可伸缩性(使用未命名信号量)比System V信号量高得多。在用户/客户端场景中,每个用户创建自己的服务器实例时,最好使用POSIX信号量。
- 当创建信号量对象时,System V信号量创建一个信号量数组,而POSIX信号量只创建一个信号量。因此,与POSIX信号量相比,System V信号量的信号量创建(占用内存方面)更昂贵。
- 据说POSIX信号量的性能比基于System V的信号量好。
- POSIX信号量提供了进程范围的信号量机制,而不是系统范围的信号量机制。因此,如果开发人员忘记关闭信号量,则在进程退出时会清除信号量。简单地说,POSIX信号量提供了一种用于非持久信号量的机制。
POSIX 共享/命名信号量用于不同进程(而非线程)存在两个主要问题: 1. POSIX 信号量没有机制可以在一个持有信号量锁的进程死亡时唤醒等待进程。这种缺乏清理机制可能导致僵尸信号量,从而导致任何其他或后续尝试使用它们的进程死锁。此外,在操作系统中列出信号量并尝试识别和清理它们也没有 POSIX 的方法。POSIX SysV IPC 部分确实指定了 ipcs 和 ipcrm 工具来列出和操作全局 SysV IPC 资源。对于 POSIX IPC,没有指定这样的工具甚至机制,但在 Linux 中,这些资源通常可以在 /shm 下找到。这意味着在错误的时间向错误的进程发送 KILL 信号可能会导致整个交互进程系统死锁,直到重新启动。
另一个缺点是在POSIX信号量中使用文件语义。这意味着可以有多个具有相同名称但不同状态的共享信号量。例如,进程调用sem_open,然后在sem_close之前调用sem_unlink。这个进程仍然可以像在关闭打开的文件之前删除它一样使用信号量。进程2在进程1调用sem_unlink和sem_close之间对同一信号量调用sem_open,根据文档,会得到一个全新的具有相同名称但与进程1处于不同状态的信号量。两个独立操作的具有相同名称的共享信号量会破坏共享信号量的目的。 第一个限制使得在没有保证无法发送不可捕获信号的实际系统中无法使用POSIX共享信号量。第二个限制可以通过仔细编码来缓解,假设控制将使用给定信号量的所有代码。说实话,它们被纳入标准中还是有些出乎意料的。我知道这篇文章有些过时了,但为了那些通过谷歌来查看这篇文章的人们,我想说,我发现使用System V信号量比使用POSIX(系统级)信号量更好的原因是能够以一种自动返回内核控制权的方式获取信号量资源,不管进程以何种方式退出。
我同意多个(原子性)信号量操作很少被使用(尽管在阶段性操作中它们可能非常有用),并且System V接口很奇怪,但是使用POSIX信号量根本无法可靠地实现相同的清除语义。