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

gim*_*ilk 14 memory shared ipc

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

void getBuffer (void **ppBuf, unsigned long *pSize);
void bufferFilled (void *pBuf, unsigned long size);
Run Code Online (Sandbox Code Playgroud)

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

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

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

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

[other process]
myLocalBuf = openTheSharedMemory (shmName);
Run Code Online (Sandbox Code Playgroud)

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

Fra*_*kH. 9

有充分的理由为使此功能,特别是从事物的安全方面."共享此内存"API将破坏访问权限系统.

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

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

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

编辑:为了清楚说明,过程边界明确是关于不共享地址空间(以及其他内容).
如果您需要共享地址空间,请使用线程(然后共享整个地址空间,并且从不需要"导出"任何内容),或者以与设置方式相同的方式显式设置共享内存区域共享文件.

从后一种观点来看,没有打开它的两个进程O_EXCL将共享对文件的访问.但是,如果一个进程已经打开它O_EXCL,则只能以"让共享"(开能到另一个进程)的方式是close()第一次,然后open()没有O_EXCL.没有其他方法可以从您打开的文件中"删除"独占访问权限,而不是先关闭它.
就像没有办法删除对映射为内存区域的独占访问权限而不是首先取消映射 - 而对于进程'内存,这MAP_PRIVATE是默认的,这是有充分理由的.

更多:进程共享内存缓冲区实际上与进程共享文件没有太大区别; 使用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连接的两端都可以使用该密钥来检查共享资源是否存在以及访问(尽管如此,附上手柄)的内容.


Nem*_*emo 5

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

从本质上讲,这是将文件放置在ramdisk(tmpfs)上的一种便携式方法。因此,一个过程使用shm_openplus ftruncateplus mmap。其他用途shm_open(具有相同的名称)加mmapplus shm_unlink。(具有两个以上的进程,最后一个映射它可以取消链接。)

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

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