加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 服务器 > Linux > 正文

在/ dev / shm的子目录中创建共享内存时,linux-shm_open()因EINV

发布时间:2020-12-14 01:28:27 所属栏目:Linux 来源:网络整理
导读:我有一个GNU / Linux应用程序,它使用了许多共享内存对象.它可能会在同一系统上运行多次.为了保持整洁,我首先在/ dev / shm中为每个共享内存对象集创建一个目录. 问题是在较新的GNU / Linux发行版上,我似乎不再能够在/ dev / shm的子目录中创建它们. 以下是一
我有一个GNU / Linux应用程序,它使用了许多共享内存对象.它可能会在同一系统上运行多次.为了保持整洁,我首先在/ dev / shm中为每个共享内存对象集创建一个目录.

问题是在较新的GNU / Linux发行版上,我似乎不再能够在/ dev / shm的子目录中创建它们.

以下是一个最小的C程序,说明了我在说什么:

/*****************************************************************************
* shm_minimal.c
*
* Test shm_open()
*
* Expect to create shared memory file in:
*  /dev/shm/
*  └── my_dir
*   ?? └── shm_name
*
* NOTE: Only visible on filesystem during execution.  I try to be nice,and
*       clean up after myself.
*
* Compile with:
*   $gcc -lrt shm_minimal.c -o shm_minimal
*
******************************************************************************/

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <sys/types.h>


int main(int argc,const char* argv[]) {
  int shm_fd = -1;

  char* shm_dir = "/dev/shm/my_dir";
  char* shm_file = "/my_dir/shm_name";      /* does NOT work */
  //char* shm_file = "/my_dir_shm_name";    /* works */

  // Create directory in /dev/shm
  mkdir(shm_dir,0777);

  // make shared memory segment
  shm_fd = shm_open(shm_file,O_RDWR | O_CREAT,0600);

  if (-1 == shm_fd) {

    switch (errno) {
    case EINVAL:
      /* Confirmed on:
       *  kernel v3.14,GNU libc v2.19  (ArchLinux)
       *  kernel v3.13,GNU libc v2.19  (Ubuntu 14.04 Beta 2)
       */
      perror("FAIL - EINVAL");
      return 1;

    default:
      printf("Some other problem not being testedn");
      return 2;
    }

  } else {
    /* Confirmed on:
     *  kernel v3.8,GNU libc v2.17    (Mint 15)
     *  kernel v3.2,GNU libc v2.15    (Xubuntu 12.04 LTS)
     *  kernel v3.1,GNU libc v2.13    (Debian 6.0)
     *  kernel v2.6.32,GNU libc v2.12 (RHEL 6.4)
     */
    printf("Success !!!n");
  }

  // clean up
  close(shm_fd);
  shm_unlink(shm_file);
  rmdir(shm_dir);
  return 0;
}


/* vi: set ts=2 sw=2 ai expandtab:
 */

当我在一个相当新的发行版上运行这个程序时,对shm_open()的调用返回-1,并且errno设置为EINVAL.但是,当我运行较旧的东西时,它会按预期在/ dev / shm / my_dir中创建共享内存对象.

对于更大的应用程序,解决方案很简单.我可以使用公共前缀而不是目录.

如果你可以帮助我了解这种明显的行为改变,那将会非常有帮助.我怀疑其他人可能会尝试做类似的事情.

解决方法

事实证明,问题源于GNU libc如何验证共享内存名称.具体来说,共享内存对象现在必须位于shmfs挂载点的根目录.

由于错误BZ #16274,这在glibc git commit b20de2c3d9中发生了变化.

具体来说,改变是这样的:

if (name[0] == '' || namelen > NAME_MAX || strchr (name,'/') != NULL)

现在不允许文件名中的任何位置使用’/'(不包括前导’/’)

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读