【问题标题】:Behaviour of shm_unlinkshm_unlink 的行为
【发布时间】:2021-01-23 14:10:22
【问题描述】:

我有以下代码 sn-p :

fd_mem = shm_open(MEM_NAME , O_RDWR | O_CREAT | O_EXCL , 0600);

//Why do we use unlink before having mmaped ? 
shm_unlink ( MEM_NAME );

ftruncate (fd_mem , mem_size)
    
plateau = (char*) mmap(NULL , mem_size , PROT_READ | PROT_WRITE , MAP_SHARED , fd_mem , 0);

我的问题是:为什么我们在将文件映射到进程的虚拟内存之前使用“取消链接”?我对shm_unlink() 在这方面的工作方式感到困惑。我认为它会删除使 fd_mem 无法使用的文件,但它不会。

【问题讨论】:

    标签: c linux shared-memory code-cleanup


    【解决方案1】:

    我对 shm_unlink 在这方面的工作方式感到困惑,我认为它会删除导致 fd_mem 不可用的文件,但事实并非如此。

    shm_unlink() 删除共享内存段的name。只要任何进程打开该段本身,它就会一直存在,但在取消链接后,进程将无法再打开它。即便如此,从一个持有共享内存段的进程派生出来的新进程会继承这一点,并且一个进程可以通过 UNIX 域套接字将文件描述符复制到另一个进程,因此取消链接不会固有地限制哪些进程或多少进程可以访问该段.

    这与普通文件和unlink() 的情况完全相同。成功取消链接文件名会从其目录中删除该名称,但只要有任何进程打开该文件,该文件本身就不会被删除。

    做这种事情的原因之一是

    • 确保无论何时何地进程终止都会清理资源。只要命名的共享内存段保持链接或进程保持打开状态,它们就会一直存在。通过在创建和打开分段后立即取消链接,进程有助于确保它不会比预期的寿命更长,即使该进程崩溃。

    • 以避免不必要的访问。任何具有足够权限的进程都可以打开命名的共享内存段。取消链接共享内存段有助于控制它。它尤其有助于避免同一程序的多个副本不必要地共享使用。

    还请注意,可以创建匿名共享内存段,这些段从一开始就不会链接到名称。这就像创建、打开并立即取消链接的命名段一样,但它没有留下任何窗口,另一个进程可以在其中不经意地按名称打开该段。

    【讨论】:

    • 感谢您提供如此完整的答案。
    • 这与普通文件和unlink() 的情况完全类似。the glibc implementation... 中的情况类似。POSIX 共享内存的 glibc 实现仅此而已而不是仅仅打开和取消链接常规文件,而是在预定义的目录中。
    【解决方案2】:

    打开文件或共享内存段会增加底层“内核对象”上的引用计数器。删除操作,删除对象的名称但不减少引用计数器。只要引用计数器大于 0,对象就不会被销毁。

    打开对象后删除对象,是为了在进程自愿(退出)或非自愿(收到信号)终止时自动清理:终止触发“关闭”操作,该操作会减少引用计数器。当后者降到0时,对象也消失了,因为删除操作也完成了。

    如果没有这些技巧,进程可能会在不进行任何清理的情况下终止,从而在文件系统中留下“垃圾”条目。

    【讨论】:

      【解决方案3】:

      好的,发生的情况是,只有在没有更多对该文件的引用时才会删除文件,这包括打开的文件描述符,并且由于我们有 fd_mem,shm_unlink 将删除 /dev/shm/MEM_NAME 中的链接,但是文件在 fd_mem 关闭之前不会被删除。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-07-10
        • 2019-06-05
        • 1970-01-01
        相关资源
        最近更新 更多