【问题标题】:Why call shm_unlink first before calling shm_open?为什么在调用 shm_open 之前先调用 shm_unlink?
【发布时间】:2017-09-21 14:44:36
【问题描述】:

我在一个遗留项目中看到了以下代码模式:

  1. 检查是否已创建名为“/abc”的共享内存:

    int fd = shm_open("/abc", O_RDWR, 0777);
    if(fd != -1)
    {
      close(fd);
      return -1;
    }
    
  2. 移除之前由shm_open()创建的对象:

    shm_unlink("/abc");
    
  3. 创建一个共享内存对象:

    fd = shm_open("/abc", (O_CREAT | O_RDWR), S_IWUSR);
    

第 2 步是多余的吗?

代码可以运行到第 2 步,因为“/abc”的共享内存对象不存在。换句话说,如果对象确实存在,代码就会返回。为什么要显式调用 shm_unlink 来移除不存在的对象?

我们可以将这三个步骤缩短为一个吗?

我认为我们可以如下进行,我们使用标志O_EXCL 来检查是否存在旧内存对象,如果根本不存在则创建它。 shm_open() 手册页说:

O_EXCL

如果还指定了 O_CREAT,并且共享内存对象 给定名称已经存在,返回错误。这 检查对象是否存在,如果 它不存在,以原子方式执行。

所以把上面的所有代码都换成一行应该没问题:

int fd = shm_open("/abc", O_RDWR | O_EXCL, 0777);

对吗?

【问题讨论】:

  • 应该替换原始序列,因为它包含一个竞争窗口,另一个进程可以利用该窗口来访问共享内存。

标签: c linux shared-memory


【解决方案1】:

第 2 步是多余的吗?

是的。它没有任何作用。

除了这种“检查存在”之外,还容易出现TOCTOU 漏洞。

我们可以将上面的 3 步缩短为一个步骤吗

是的。这是正确的做法。但是您还需要O_CREAT 标志(您的代码中缺少该标志)。

【讨论】:

    猜你喜欢
    • 2018-03-27
    • 2011-04-19
    • 1970-01-01
    • 2015-07-31
    • 2012-08-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-09-12
    相关资源
    最近更新 更多