我正在将现有的 Win32 代码移植到 Linux。在 Windows 上,我有一个“主”进程,即“读取器”,它创建一个共享内存对象,然后等待一些“从属”进程,即“写入器”,将数据放入共享内存中进行处理。
主进程:Win32 实现依赖于 CreateFileMapping( INVALID_HANDLE_VALUE, [...]
后跟 MapViewOfFile
。 中指定的共享内存大小 si >CreateFileMapping
调用。将 0 作为最后一个参数传递给 MapViewOfFile
可确保映射所有共享内存。在 Linux 上,经过一些谷歌搜索后,我得出结论,我应该使用 shm_open
+ ftruncate
+ mmap
.
Slave进程:Win32实现与Master进程几乎相同,只是CreateFileMapping
被OpenFileMapping
代替,VirtualQuery
可用于获取共享内存的大小。
在 Linux 上,我遇到了一个问题:“从属”进程必须以某种方式“等待”ftruncate
调用在“主”进程中完成。他们不能自己执行 ftruncate
,因为他们还不知道共享内存的大小。
“从属”进程在 fstat
beetwen shm_open
和 mmap
上轮询是否可以?或者这是不好的做法,如果是,是否有另一种映射“好”尺寸的方法?
编辑:
暂时不想直接使用File System。我喜欢这样一个事实,即我可以通过使用将在 2 个平台上工作的“名称”创建一个“命名共享内存对象”,如 "/MySharedMemName42"
并且不想关心文件的位置。如果看起来不现实,我可能会改变主意。
我知道在使用共享内存时,主进程和从进程必须合作。他们通过写入/读取内存来做到这一点。 “问题”是如果存在竞争(ftruncate 在主机中迟到),shm_open/mmap 可能会导致从机中出现 SIGBUS。我测试了“fstat polling”是否有效,但想知道它是否被视为一个糟糕的 hack,或者是处理比赛的正确方法。
最佳答案
如果我理解正确,Windows CreateFileMapping 调用是 UNIX 节“shm_open+ftruncate+maybe-mmap”的原子 版本,因此在 UNIX 上有可能客户端可以在共享内存大小合适之前访问它。
因此,您建议使用 fstat
没问题。这是officially supported通过 POSIX 共享内存选项。您的设计似乎可以容忍共享内存区域是否存在的轮询,因此轮询它的正确大小(或至少 st_size > 0
)也应该没问题。
或者,您可以在打开期间使用共享内存区域的模式(O_CREAT|O_EXCL 和 0600),并在准备就绪时fchown
— 您的从属进程,取决于 UID 和 GID,在内存准备好之前,会因 ENOENT 或 EACCES 而失败。这又是一个“轮询”选项。您还可以在调整大小后重命名共享内存本身(通过 Linux 的 /dev/shm/
),但这是一种非 POSIX 便利。
(现在,如果您的下属是主人的 child ,那么您可以依靠古老的 *NIX 进程继承技术并切换到未命名的共享内存...)
关于linux - 在 shm_open 和 mmap 之间使用 fstat,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20501290/