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

Memory Unix:在进程之间共享已映射的内存,memory,ipc,shared,Memory,Ipc,Shared,我有一个预构建的用户空间库,它有一个API void getBuffer (void **ppBuf, unsigned long *pSize); void bufferFilled (void *pBuf, unsigned long size); 我的想法是,我的代码从库中请求一个缓冲区,用东西填充它,然后将它交还给库 我希望另一个进程能够填充此缓冲区。我可以通过shm*/shm_*api创建一些新的共享缓冲区,让另一个进程填充它,然后将其复制到lib本地进程中的lib缓冲区,但这会增加

我有一个预构建的用户空间库,它有一个API

void getBuffer (void **ppBuf, unsigned long *pSize);
void bufferFilled (void *pBuf, unsigned long size);
我的想法是,我的代码从库中请求一个缓冲区,用东西填充它,然后将它交还给库

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

是否有一种方法可以共享已映射到进程的内存?例如:

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

[other process]
myLocalBuf = openTheSharedMemory (shmName);
这样,另一个进程就可以直接写入lib的缓冲区。
(进程之间的同步已得到处理,因此不会出现任何问题)。

不允许使用此功能有很好的理由,特别是从安全方面考虑。“共享此mem”API将破坏访问权限系统

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

承认,这不适合您的用例,但从系统/应用程序完整性的角度来看是合理的。请尝试在web上搜索/proc/pid/mem mmap漏洞,以了解不需要这种访问的原因(通常)

如果您使用的库被设计为允许这种共享访问,那么它本身必须提供钩子来分配这种共享缓冲区,或者使用在别处预先分配(可能是共享)的缓冲区

编辑:为了澄清这一点,进程边界明确表示不共享地址空间(以及其他内容)。
如果您需要一个共享的地址空间,可以使用线程(这样整个地址空间都是共享的,不需要“导出”任何内容),也可以按照设置共享文件的方式显式设置共享内存区域

从后一个角度来看,两个进程不打开它将共享对文件的访问权。但是,如果一个进程已经将其打开,那么“使其共享”(可以打开到另一个进程)的唯一方法是先关闭它,然后再打开它,而不使用
O_EXCL
。除了先关闭文件外,没有其他方法可以从已打开的文件中“删除”独占访问权限。
正如除了首先取消映射之外,没有办法删除对映射为这样的内存区域的独占访问—对于进程的内存,
MAP\u 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() |SysV IPC共享内存文件 ==============+=================================================================== 创建| id=shmget(键,…,IPC|u创建);fd=打开(“名称”、…、O_CREAT); 查找| id=shmget(键,…);fd=开放(“名称”,…); 访问| addr=shmat(id,…);addr=mmap(…,fd,…); | 全局句柄| IPC密钥文件名 本地句柄| SHM ID号文件描述符号 mem位置|由shmat()创建由mmap()创建
也就是说,密钥是您正在寻找的“句柄”,以与传递文件名相同的方式传递,然后IPC连接的双方都可以使用该密钥检查共享资源是否存在,以及通过该密钥访问(附加到句柄)内容。

至少在理论上,您可以记录从lib获得的缓冲区的内存地址,并让另一个进程mmap/proc/$PID\u of_FIRST\u PROCCESS/mem文件将地址作为偏移量


我还没有测试过它,我不确定/proc/PID/mem是否真的实现了一个mmap文件op,还有很多安全方面的考虑,但它可能会工作。祝您好运:-)

在进程之间共享内存的更现代的方法是使用

本质上,它是一种将文件放在ramdisk(tmpfs)上的便携式方式。因此,一个进程使用
shm_open
plus
ftruncate
plus
mmap
。另一个使用
shm\u open
(同名)加
mmap
plus
shm\u unlink
。(对于两个以上的进程,最后一个到mmap的进程可以取消链接。)

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


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

谢谢您的回复。我正在开发一个嵌入式系统,它有多个进程通过IPC消息传递进行通信。这对于大多数需要来回传递小消息的操作都非常有效,但进程也需要相互传递大的数据缓冲区。因此,出于性能原因,我希望有一个特殊的“快捷方式”,可以在消息中传递一些共享内存句柄,而不必复制整个缓冲区(通过管道或另一个中间共享内存段);要传递的手柄是SHM IPC键。所有用户/共享者然后使用shmget/shmat获取缓冲区地址(在他们的地址空间内)。谢谢FrankH。不幸的是,这两种方法都要求我是内存的创建者,但我需要让不透明库创建的内存可以共享。如果你可以在你的平台上控制内核,那么就编写一个设备驱动程序,通过e。