Las*_*ssi 8 unix posix shared-memory
POSIXshm_open()函数返回可用于访问共享内存的文件描述符。这非常方便,因为可以使用所有传统的控制文件描述符的机制来控制共享内存。
唯一的缺点是shm_open()总是需要一个文件名。所以我需要这样做:
// Open with a clever temp file name and hope for the best.
fd = shm_open(tempfilename, O_RDWR | O_CREAT | O_EXCL, 0600);
// Immediately delete the temp file to keep the shm namespace clean.
shm_unlink(tempfilename);
// Then keep using fd -- the shm object remains as long as there are open fds.
Run Code Online (Sandbox Code Playgroud)
这种使用tempfilename很难便携和可靠地进行。文件名的解释(命名空间是什么,权限的处理方式)因系统而异。
在许多情况下,使用共享内存对象的进程不需要文件名,因为只需将文件描述符从一个进程传递到另一个进程,就可以更简单、更安全地访问该对象。那么有没有类似shm_open()但可以在不触及共享内存文件名命名空间的情况下使用的东西?
mmap()withMAP_ANON|MAP_SHARED很棒,但它不是文件描述符,而是提供了一个指针。指针不能在 exec 边界上存活,也不能像文件描述符那样通过 Unix 域套接字发送到另一个进程。
shm_open()默认情况下,由 返回的文件描述符也不会在 exec 边界中存活:POSIX 定义表示设置了与新文件描述符关联的 FD_CLOEXEC 文件描述符标志。但是可以fcntl()在 MacOS、Linux、FreeBSD、OpenBSD、NetBSD、DragonFlyBSD 和可能的其他操作系统上清除标志。
Las*_*ssi 11
int shm_open_anon(void);
Run Code Online (Sandbox Code Playgroud)
该库编译时没有警告,并在 Linux、Solaris、MacOS、FreeBSD、OpenBSD、NetBSD、DragonFlyBSD 和 Haiku 上成功运行了一个测试程序。您或许可以使其适应其他操作系统;如果你这样做,请发送拉取请求。
该库返回一个设置了 close-on-exec 标志的文件描述符。您可以fcntl()在所有支持的操作系统上使用清除该标志,这将允许您将 fd 传递到exec(). 测试程序表明这是有效的。
该库的自述文件对每个操作系统已完成和未完成的操作有非常精确的说明。这是主要内容的摘要。
有几个不可移植的东西或多或少相当于shm_open()没有文件名:
FreeBSD 可以SHM_ANON作为shm_open()自 2008 年以来的路径名。
Linuxmemfd_create()从内核版本 3.17 开始就有一个系统调用。
早期版本的 Linux 可以使用mkostemp(name, O_CLOEXEC | O_TMPFILE)where 之类name的东西/dev/shm/XXXXXX。请注意,我们shm_open()在这里根本没有使用--mkostemp()隐式地使用了一个非常普通的open()调用。Linux 在其中安装了一个特殊的内存支持的文件系统,/dev/shm但一些发行版使用它,/run/shm因此这里存在陷阱。而且您仍然必须 shm_unlink() 临时文件。
OpenBSDshm_mkstemp()从 5.4 版开始有一个调用。您仍然需要shm_unlink()临时文件,但至少它很容易安全地创建。
对于其他操作系统,我执行了以下操作:
为 POSIX的name参数找出依赖于操作系统的格式shm_open()。请注意,没有任何名称可以传递是绝对可移植的。例如,NetBSD 和 DragonFlyBSD 对名称中的斜杠有冲突的要求。即使您的目标是使用命名的 shm 对象(POSIX API 就是为此设计的)而不是匿名对象(正如我们在这里所做的那样),这也适用。
在名称后附加一些随机字母和数字(通过阅读/dev/random)。这基本上就是mktemp()这样做的,除了我们不检查我们的随机名称是否存在于文件系统中。name参数的解释千差万别,因此没有合理的方法将其可移植地映射到实际文件名。此外,Solaris 并不总是提供mktemp(). 出于所有实际目的,我们输入的随机性将确保我们需要的几分之一秒的唯一名称。
通过shm_open(name, O_RDWR | O_CREAT | O_EXCL | O_NOFOLLOW, 0600).打开具有该名称的 shm 对象。在我们的随机文件名已经存在的天文机会中,O_EXCL无论如何都会导致此调用失败,因此不会造成任何伤害。0600在某些系统上,权限(所有者读写)是必需的,而不是空白0权限。
立即调用shm_unlink()以摆脱随机名称。文件描述符保留供我们使用。
POSIX 不保证此技术有效,但是:
shm_open() 名参数由POSIX所以没有做任何保证更好地工作,得以确认。享受。