我正在将现有的Win32代码移植到Linux中。 在Windows上,我有一个“主”进程,即“reader”,它创build一个共享内存对象,然后等待一些“从属”进程,即“编写者”将数据放入共享内存中进行处理。
主进程:Win32实现依赖于CreateFileMapping( INVALID_HANDLE_VALUE, [...]
接着是MapViewOfFile
, CreateFileMapping
调用中指定的共享内存si的大小,将0作为最后一个parameter passing给MapViewOfFile
确保所有的共享内存映射在Linux上,一些谷歌search后,我总结说我应该使用shm_open
+ ftruncate
+ mmap
。
从属过程:除了将CreateFileMapping
replace为OpenFileMapping
之外,Win32实现与主进程几乎相同,并且VirtualQuery
可用于获取共享内存的大小。
在Linux上,我有一个问题:“从”进程必须以某种方式“等待”在“主”进程中完成ftruncate
调用。 他们不能自己动手,因为他们对共享内存的大小没有任何意见。
可以在fstat
beetwen shm_open
和mmap
上查询“slave”进程吗? 或者这是不好的做法,如果是的话,是否有另一种方法来缩小“好”的尺寸?
编辑:
目前,我不想直接使用文件系统。 我喜欢这样一个事实,即我可以使用一个可以在2个平台上工作的名字"/MySharedMemName42"
来创build一个“命名的共享内存对象”,并且不需要关心文件的位置( S)。 如果看起来不现实,我可能会改变主意。
我知道当使用共享内存时,主进程和从进程必须配合。 他们通过写/读内存来做到这一点。 这个“问题”是,如果存在竞争(在主站中延迟),shm_open / mmap可能会导致从站中的SIGBUS。 我testing了“fstat polling”是否能够做到这一点,但是想知道它是否被视为一种可怕的黑客攻击,或者是一种正确的方式来对付这场竞赛。
如果我理解正确,Windows CreateFileMapping调用是UNIX节的原子版本“shm_open + ftruncate +也许-MMAP “,因此在UNIX上,客户端可以在正确调整大小之前访问共享内存。
所以,你提出的使用fstat
是好的。 它由POSIX共享内存选项正式支持 。 您的设计似乎容忍轮询共享内存区域的存在,所以轮询正确的大小(或至少st_size > 0
)也应该是正常的。
或者,也可以在打开时(O_CREAT | O_EXCL和0600)使用共享内存区域的模式 ,并在准备就绪时启用它 – 根据UID和GID,您的下级进程将会因ENOENT或EACCES而失败,直到内存准备就绪。 这又是一个“轮询”选项。 您也可以在调整共享内存本身的大小(通过Linux的/dev/shm/
),但这是非POSIX的便利。
(现在,如果你的下属是主人的孩子 ,那么你可以依靠这种古老的* NIX技术的进程继承和切换到无名共享内存…)
在两个平台上都有同样的问题 – 您需要从服务器等待主服务器设置共享区域。
在Windows的情况下,你有奴隶试图打开一个具有特定名字的文件映射,并重试,如果与该名称的映射不存在。
虽然不是一个理想的解决方案,但是你可以在Linux上做同样的事情。
请注意,您不一定需要POSIX共享内存对象。 你可以使用一个普通的文件。 首先,用普通的open(2)
和ftruncate(2)
创建和设置文件大小,但是使用一个临时唯一的随机生成的名字。 然后rename(2)
从临时名称到知名名称的文件。