【问题标题】:what happen if fail to delete a shared memory segment如果无法删除共享内存段会发生什么
【发布时间】:2019-07-24 18:03:11
【问题描述】:

根据我的观察,如果我在不删除共享内存段的情况下终止进程,则该共享内存段将留在/dev/shm/xxxx 中,甚至没有其他进程正在使用它。 是否意味着内存泄漏?(并且在我重新启动机器后它会消失)为什么linux没有提供一种机制来维护共享内存的引用计数,然后系统可以在没有时删除它进程正在使用它。

由于进程可能崩溃,或者我只是未能捕获一些异常......无论如何,当进程异常终止时,我很有可能无法删除该共享内存段。

我的用例:我正在运行多个共享同一内存段进行通信的工作进程。并且没有主节点来协调事情。策略是最后一个退出节点将关闭共享内存段。

顺便说一句,我使用的是boost::interprocess 而不是系统级别的shm_open,但我认为它们的行为应该是相同的。

【问题讨论】:

  • 你怎么知道哪个是最后一个出口节点?
  • 通常,您想知道哪个节点是第一个启动的。该节点应该清理所有遗留的混乱,然后创建一个新的共享内存段。
  • 可以得到你描述的行为:创建并映射一个共享内存对象后,使用shm_unlink将其与名称解除关联。它将继续存在直到最后一个引用被关闭,例如当最后一个映射它的进程取消映射它时。
  • @user3386109 可能是通过文件锁定或其他方式......因为我可以知道有多少进程正在打开一个文件,即使进程崩溃,该文件的引用计数也会减少。

标签: c linux multiprocessing shared-memory


【解决方案1】:

Posix 标准要求(强调):

创建共享内存对象时,共享内存对象的状态,包括与共享内存对象关联的所有数据,一直保持到共享内存对象被取消链接并且所有其他引用都消失了.未指定名称和共享内存对象状态在系统重新启动后是否保持有效。

换句话说,共享内存对象基本上就像临时文件;它们旨在保持持久性,至少在会话期间是这样。所有使用特定命名共享内存对象的进程都可能崩溃,您仍然可以启动一个新进程并恢复共享内存对象的内容。

由于 Linux 试图与 Posix 标准保持一致,它以相同的方式实现共享内存对象,这意味着除非手动清理它们,否则它们会一直存在(直到重新启动)。

不再被任何活动进程使用的共享内存对象并不完全是内存泄漏,因为如果存在内存压力(并且启用了交换),它将迅速被换出。但是,最好自己定期清理共享内存对象。根据您的应用程序的具体性质,有多种策略可以做到这一点。

一个简单(但绝不是通用的)解决方案是在您知道不需要新进程打开共享内存对象后立即取消链接。取消链接对象有效地删除了它的名称,因此不再可能shm_open 它,但只要某个进程对它有开放引用,取消链接的对象就会持续存在。 (操作系统确实保留了引用计数;但是,只要名称存在,对象就会被计为引用。)创建临时文件的应用程序也经常使用相同的策略。

【讨论】:

    猜你喜欢
    • 2016-03-12
    • 2011-09-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-10-03
    • 2013-03-14
    • 1970-01-01
    • 2011-06-28
    相关资源
    最近更新 更多