为什么使用shm_open?

33

shm_open 然后跟上一个 mmap 有什么优势呢?
为什么不创建一个普通文件,然后将该 fd 传递给 mmap
我看不出 shm_open 的优势 - 这些只是引用,不是吗?

我已经阅读了整个手册。在我看来,“秘密”就在于 mmap 操作 - 文件“类型”似乎毫无意义。

任何指针都是好的,特别是涉及性能方面的。
我的背景是一个(循环可覆盖的)缓冲区(例如128MB),将由一个进程不断写入,并由另一个进程不断卸载。

举个例子:这个 打开/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...);

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

2
试一下吧。写入文件可能会慢上百倍。 - Jens Gustedt
4个回答

34
如果您打开和mmap()一个常规文件,则数据将以该文件的形式存在。
如果您仅需要共享内存区域,而无需保留数据(这会产生额外的I/O开销),请使用shm_open()。
这样的内存区域还允许您存储其他类型的对象,例如互斥锁或信号量,在大多数系统上,您不能将它们存储在mmap ()中的常规文件中。

1
如果我在/dev/shm文件系统下创建文件,例如open("/dev/shm/myshm", "w"),那怎么办呢?使用shm_open有什么优势? - Trevor
11
如果你使用shm_open或open,那么基本上是一样的,但请记住这只适用于Linux。当存在标准方法时,这样做可能没有太多意义。如果/dev/shm挂载在非标准位置,shm_open会注意到它的位置。 - nos
1
感谢您指出可移植性问题。我们的产品以虚拟机的形式提供给客户,因此我们可以控制代码运行的分发方式,从而管理它。让我困扰的是无法在/dev/shm文件系统下创建逻辑目录。这是glibc的shm_open的一个副作用,并不是文件系统的问题 - 所以我选择使用open()。 - Trevor
3
@Trevor,请注意根据POSIX标准:“名称中除了首斜杠字符以外的斜杠字符的解释是由实现定义的。”为什么不坚持使用标准API调用并简单地解决它的限制,例如使用下划线或其他特殊字符来分隔文件名的逻辑部分,而不是在/dev/shm下创建目录? - Hristo Iliev
1
你提出的建议确实是正确的 - 我仍在考虑。然而,例如,如果我想在 /dev/shm 下执行 inotify 操作,我必须使用 /dev/shm 上的 inotify - 并且会暴露给在此空间注册的其他进程。这只是我想到的一个例子。 - Trevor
显示剩余4条评论

7

1
关键区别:shm_dir前缀通常指向临时文件系统(例如tmpfs)的挂载点。 - TheDiveO

3

在现代Linux上,这两个调用本质上是等价的。第一种方法可以用于从诸如Go之类的语言中访问POSIX共享内存(请参见https://github.com/fabiokung/shm/blob/master/shm_linux.go),其中POSIX共享内存不是本地可用的。对于其他OS/版本,第一个调用可能会导致某些文件创建或/dev/shm不可用,性能也可能较慢。路径合并规则也可能随着librt版本的变化而不断发展。

第一种方法称为内存映射文件API(在std libs中支持)。

第二种方法称为POSIX共享内存API(在Linux上需要librt,也称为libposix作为依赖项。它内部构建路径并调用open)。


0

在Linux上,mmap(fopen(/dev/shm))和shm_open是相同的。

它们在Mac上不同,因为Mac上不存在/dev/shm!

在Mac上,您可以尝试执行mmap(fopen(some_other_dir)),但是然后您将遇到困难,以确定some_other_dir是否也在基于RAM的文件系统上,因此它是否与shm_open一样高效。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接