System V和Posix信号量的区别

33

使用System V和Posix信号量之间的权衡是什么?

4个回答

58

来自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信号量提供了一种用于非持久信号量的机制。

1
sem_wait()/sem_post()的性能通常更好,当信号量在共享内存中设置时,它们只调用内核来休眠或唤醒。增量/减量部分可以在无需系统调用的情况下完成。SysV信号量总是调用系统调用。这在某些情况下可能会产生巨大的负载差异。 - Patrick Schlüter

27

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共享信号量。第二个限制可以通过仔细编码来缓解,假设控制将使用给定信号量的所有代码。说实话,它们被纳入标准中还是有些出乎意料的。

此外,将POSIX信号量作为递归锁并不容易,并且它们具有奇怪的特性,即当某人多次解锁(sem_post())一个信号量时(例如出于错误),则随后的锁定(sem_wait())将使其保持打开状态。另一种处理方式:0-未锁定,任何其他值-已锁定(设置最大值),可以解决上述两个问题。 - Radoslaw Garbacz
2
信号量用于向其他进程或线程发出信号。因此,它们不用于锁定,也不会被保留。如果您想要所有权语义,必须使用互斥锁而不是信号量(请参见pthread_mutex_t)。特别是,如果您想在持有锁的同时被通知另一个进程的死亡,则应将互斥锁标记为进程共享和鲁棒性。 - Mabus

11

我知道这篇文章有些过时了,但为了那些通过谷歌来查看这篇文章的人们,我想说,我发现使用System V信号量比使用POSIX(系统级)信号量更好的原因是能够以一种自动返回内核控制权的方式获取信号量资源,不管进程以何种方式退出。

我同意多个(原子性)信号量操作很少被使用(尽管在阶段性操作中它们可能非常有用),并且System V接口很奇怪,但是使用POSIX信号量根本无法可靠地实现相同的清除语义。


3
抱歉,我不太明白你所说的“以一种无论进程如何退出都会自动返回内核的信号量资源获取能力”的意思。你能否再解释一下? - Fingolfin
@xci13:如果进程被强制终止(例如使用SIGKILL),信号量不会自动释放。请参见iggie的答案 - Craig McQueen

0
关于性能,POSIX信号量基于Linux下的futex。这使它们比SYSV信号量更有效。
SYSV信号量需要系统调用来进行P()/V()操作。因此,这会引起用户到内核空间的上下文切换和相反的情况。
在POSIX版本中,底层的futex使调用者在没有信号量争用的情况下保持在用户空间(使用可用的原子操作在用户空间执行P()/V()操作)。只有在存在争用的情况下才会切换到内核模式。因此,在使用POSIX信号量的应用程序中,用户到内核空间的上下文切换和相反的情况较少。这使它们更快。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接