Unix:在进程之间共享已映射的内存

时间:2011-06-22 22:14:42

标签: memory ipc shared

我有一个预构建的用户空间库,其中包含一行

的API
void getBuffer (void **ppBuf, unsigned long *pSize);
void bufferFilled (void *pBuf, unsigned long size);

这个想法是我的代码从lib请求缓冲区,用东西填充它,然后把它交给lib。

我希望另一个进程能够填充此缓冲区。我可以通过shm * / shm_ * API创建一些新的共享缓冲区,让其他进程填充,然后将其复制到lib的本地进程中的lib缓冲区,但这会产生额外的开销(可能很大)副本。

有没有办法共享已为进程映射ALREADY的内存?例如:

[local lib process]
getBuffer (&myLocalBuf, &mySize);
shmName = shareThisMemory (myLocalBuf, mySize);

[other process]
myLocalBuf = openTheSharedMemory (shmName);

这样,其他进程可以直接写入lib的缓冲区。 (进程之间的同步已经完成,所以没有问题)。

3 个答案:

答案 0 :(得分:9)

有充分的理由允许此功能,特别是从安全方面来看。 “共享此内存”API将破坏访问权限系统。

假设某个应用程序在内存中保存某种关键/敏感信息;应用程序链接(通过例如使用共享库,预加载,修改的链接器/加载器)到外部的任何组件,并且所述组件的纯粹乐趣决定“共享地址空间”。它是一种免费的,一种绕过任何类型的数据访问权限/限制的方法。你可以通过自己的方式进入应用程序。

对您的用例不利,承认,但从系统/应用程序完整性的角度来看是合理的。尝试在网上搜索 / proc / pid / mem mmap漏洞,了解为什么不需要这种访问(一般情况下)。

如果您使用的库旨在允许此类共享访问,则它必须本身提供挂钩以分配此类共享缓冲区,或使用其他预先分配的(可能是共享的)缓冲区。

修改:为了明确这一点,进程边界明确是关于不共享地址空间(以及其他内容)。 /> 如果您需要共享地址空间,请使用线程(然后共享整个地址空间,并且永远不需要“导出”任何内容),或者以与设置方式相同的方式显式设置共享内存区域共享文件。

从后一个角度来看,两个进程打开它O_EXCL将共享对文件的访问权限。但是,如果一个进程已经打开O_EXCL,那么“让它共享”(可以打开另一个进程)的唯一方法就是close()首先然后{ {1}} 再次没有open()。没有其他方法可以从您打开的文件中“删除”独占访问权限,而不是先关闭它。
就像没有办法删除对映射的内存区域的独占访问权而不是首先取消映射 - 对于进程'内存,O_EXCL是默认值,原因很充分。

更多:进程共享内存缓冲区与进程共享文件没有太大区别;使用SysV-IPC样式语义,你有:

              | SysV IPC shared memory            Files
==============+===================================================================
creation      | id = shmget(key,..., IPC_CREAT);  fd = open("name",...,O_CREAT);
lookup        | id = shmget(key,...);             fd = open("name",...);
access        | addr = shmat(id,...);             addr = mmap(...,fd,...);
              |
global handle | IPC key                           filename
local handle  | SHM ID number                     filedescriptor number
mem location  | created by shmat()                created by mmap()

即。关键是你正在寻找的“句柄”,传递方式与传递文件名的方式相同,然后IPC连接的两端都可以使用该密钥来检查共享资源是否存在,以及访问(附加)尽管如此,还是把握了内容。

答案 1 :(得分:5)

在流程之间共享内存的更现代的方法是使用POSIX shm_open() API

基本上,它是一种将文件放在ramdisk(tmpfs)上的便携方式。因此,一个流程使用shm_openftruncatemmap。另一个使用shm_open(具有相同名称)加mmapshm_unlink。 (有两个以上的进程,mmap的最后一个进程可以取消链接。)

这样,当最后一个进程退出时,共享内存将自动回收;无需显式删除共享段(与SysV共享内存一样)。

但仍需要修改应用程序以便以这种方式分配共享内存。

答案 2 :(得分:-1)

理论上至少,您可以记录从lib获得的缓冲区的内存地址,并使用地址作为偏移量的另一个进程mmap / proc / $ PID_OF_FIRST_PROCCESS / mem文件。

我还没有测试过,我不确定/ proc / PID / mem实际上是否有一个mmap文件已经实现,并且有很多安全性考虑,但它可能会有效。祝你好运: - )