为啥使用 shm_open?

Posted

技术标签:

【中文标题】为啥使用 shm_open?【英文标题】:Why use shm_open?为什么使用 shm_open? 【发布时间】:2014-09-12 13:23:39 【问题描述】:

这样做有什么好处:shm_open 跟着mmap? 为什么不创建一个常规文件,然后将 fd 传递给 mmap? 我看不出shm_open 的优势——这些只是参考,不是吗?

我读过全家的男人。在我看来,“秘密”在映射操作中——文件“类型”似乎毫无意义。

任何指针都会很好,尤其是性能帐户。 我的上下文是一个(循环可重写)缓冲区(比如 128MB),它将不断被写入一个进程,并不断被另一个进程转储。

例如:this open/mmap 方法有什么问题。

编辑 准确地说,是以下哪一项优于另一项:

fd = open("/dev/shm/myshm.file", O_CREAT|O_RDWR, S_IRUSR | S_IWUSR);
mem = mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);

对比

fd = shm_open("/myshm.file", O_RDWR|O_CREATE, S_IRUSR | S_IWUSR);
mem = mmap(...same as before...);

当我在 /dev/shm fs 下使用常规 open 创建一个文件,并向其中转储 Gig 垃圾时,我的可用内存减少了 1G,而我的可用磁盘空间保持不变。 这两种方法有什么区别?

【问题讨论】:

试试吧。写入文件可能会慢一百倍。 【参考方案1】:

如果您打开并 mmap() 一个常规文件,数据将最终出现在该文件中。

如果您只需要共享一个内存区域,而不需要持久化数据,这会产生额外的 I/O 开销,请使用 shm_open()。

这样的内存区域还允许您存储其他类型的对象,例如互斥锁或信号量,在大多数系统上,您无法将它们存储在 mmap() 的常规文件中。

【讨论】:

但是如果我在 /dev/shm fs 下创建文件呢?像这样,open("/dev/shm/myshm", "w")?使用 shm_open 有什么好处? 那么,如果您使用 shm_open 或 open,它几乎是一样的,但请记住这是特定于 linux 的。当存在标准方法时,这将是相当轻率的。如果 /dev/shm 也安装在非标准位置,则 shm_open 会小心定位。 感谢您指出可移植性问题。我们的产品作为虚拟机提供给客户,因此我们控制代码运行的分布,因此我们可以管理它。首先让我感到困惑的是无法在 /dev/shm fs 下创建逻辑目录。这是 glibc 的 shm_open 的产物,不是 fs 的问题 - 所以我要使用 open()。 @Trevor,请注意,根据 POSIX 标准:“名称中除前导斜杠字符之外的斜杠字符的解释是实现定义的。” 为什么不坚持使用标准 API 调用并简单地解决其限制,例如通过在文件名中使用下划线或其他特殊字符来分隔逻辑部分,而不是在/dev/shm下创建目录? 你的建议确实是正确的 - 我仍然认为它。但是,例如,如果我想在 /dev/shm 下的“我们的”目录上执行和 inotify,我必须求助于在 /dev/shm 上执行 inotify - 并暴露给在此空间中注册的其他进程。想到的只是一个例子【参考方案2】:

这两个调用在现代 Linux 上本质上是等效的 - 第一种方法可用于从诸如 go(请参阅https://github.com/fabiokung/shm/blob/master/shm_linux.go)之类的语言访问 POSIX 共享内存,其中 POSIX 共享内存本机不可用 - 对于第一次调用会导致某些文件创建或 /dev 的其他操作系统/版本,它可能会有所不同/shm 只是不可用和/或性能可能较慢。路径合并的规则也可能会随着版本的 librt 演变

第一种方法称为内存映射文件 API(在标准库中支持)

第二个调用 POSIX 共享内存 API(需要 Linux 上的 librt aka libposix 作为依赖,它在内部构造路径并调用 open)

【讨论】:

【参考方案3】:

看了shm_open的源码,我可以说这两种方法差不多。

链接:https://code.woboq.org/userspace/glibc/sysdeps/posix/shm_open.c.html

shm_open 只是添加 shm_dir 前缀然后调用正常的open 系统调用,没什么特别的。

【讨论】:

以上是关于为啥使用 shm_open?的主要内容,如果未能解决你的问题,请参考以下文章

已使用 -L /lib -lrt -lpthread 未定义对“shm_open”的引用

当进程使用 shm_open() 时,Linux 内核如何分配内存指针?

对 ios7 的 shm_open 调用现在导致在 O_CREAT (EPERM) 期间不允许操作

共享内存段与共享内存对象

mmap详谈

无法定义共享内存对象的大小