POSIX命名信号量在进程退出后没有释放

6

我正在尝试使用POSIX命名信号量进行跨进程同步。我注意到,在进程死亡或退出之后,系统仍然保持着该信号量的开放状态。

是否有任何方法可以使在打开信号量的进程死亡或退出后关闭/释放它呢?


请向我们展示一个能够复现你遇到问题的例子。目前来看,很难确定是什么导致了这个问题。 - fuz
sem_overview man page 表示:"POSIX 命名信号量具有内核持久性:如果没有被 sem_unlink(3)移除,信号量将一直存在,直到系统关闭。" 如果这不能帮助您,请澄清您的问题。 - kaylum
我理解从POSIX文档中得知,当进程崩溃或退出时,默认情况下不会取消链接信号量。我只是想知道是否有任何选项或解决方法可以实现取消链接。 - S.X
@S.X “我只是想知道是否有任何选项或解决方法可以做到这一点。” - POSIX 绝对不支持此功能。一些 *nix 系统具有扩展以支持此行为,而其他一些则没有。所有可移植的“解决方案”都围绕着:定期检查(例如从 cron 脚本)应用程序是否正在运行,如果没有,则清理 SysV 资源。 - Dummy00001
2个回答

6

此前的讨论在这里:如何恢复一个信号量当将其减为零的进程崩溃时?他们在那里讨论了几种可能的解决方案。

简而言之:

  • 如果拥有信号量的进程崩溃或被信号杀死,则不会释放 POSIX 信号量。等待进程将永远等待。只要坚持使用信号量,就无法解决这个问题。
  • 可以使用套接字或文件锁来实现进程间同步,它们可以在进程退出时自动释放。我上面发布的问题的所有者最终选择了文件锁。请参见他的答案。在评论区域,他发布了一篇讨论此问题的博客链接。

其他可能有所帮助的链接:


4

您似乎在处理 进程间 通信时遇到了概念上的问题。IPC 机制的生命周期不能直接绑定到任何一个进程的生命周期,因为这会导致其他访问它的进程失去它。命名信号量的持久性是有意为之的,直到显式删除。

Linux sem_overview(7) 手册页,虽然不是权威规范,但介绍了信号量生命周期管理:

sem_open(3) 函数创建一个新的命名信号量或打开一个现有的命名信号量。打开信号量后,可以使用 sem_post(3) 和 sem_wait(3) 对其进行操作。当进程使用完信号量后,可以使用 sem_close(3) 关闭信号量。当所有进程都使用完信号量后,可以使用 sem_unlink(3) 将其从系统中删除。

根据sem_unlink()文档的说明,即使进程仍在使用信号量,也可以将其解除链接。此后,没有进程可以sem_open()该信号量,并且当拥有该信号量的进程数量降至零时,最终将对其进行清理。这故意类似于常规文件。
如果确实有一个进程应该负责清理给定的命名信号量,那么您应该确保它sem_unlink()它。两个合理的替代方案是在满足需要使用它的所有其他进程已经打开它的条件后立即取消链接,或者注册一个处理取消链接的退出处理程序。如果可行,前者可能更好。

谢谢您的回复。是否有可能拥有一个时间限制的信号量,在一定时间后自动清理自己? - S.X
@S.X,POSIX信号量没有这样的行为内置,如果可以想象这样的事情,最接近的可能是在固定延迟后取消链接的信号量。而且有几种方法可以编写程序来处理它。 - John Bollinger
我喜欢你的评论:“IPC机制的生命周期不能直接绑定到任何一个进程的生命周期上。”这对我来说很有意义! - yaobin
命名信号量在系统重启后是否会保留? - D. Jones
不,@D.Jones,命名信号量在持久存储中没有表示形式,因此它们在重启后不会继续存在。您可以在系统启动期间使它们被重新创建,但通常它们是由使用它们的应用程序根据需要创建的。 - John Bollinger
显示剩余4条评论

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