我有一个 C++ 应用程序,它通过 shmget(2) 在 Linux 系统上分配共享内存。我存储在共享内存中的数据会定期增长,我想以类似于 realloc() 增长常规内存的方式调整共享内存的大小。有没有办法做到这一点?我在 IBM 的网站上找到了一个文档,其中提到了 SHM_SIZE 命令,但是 Linux 和 BSD 联机帮助页没有它,即使在 Linux 特定的部分中也是如此。
3 回答
简单的答案:没有简单的方法。
原因很合乎逻辑。共享内存被单独附加到每个进程的虚拟空间。每个进程都有自己的虚拟地址空间。每个进程都可以自由地将段附加到任意地址(不是字面意思,对齐设置了一些限制)。系统如何保证,例如通过将区域扩展 4MiB,该段的每个“用户”都能够在先前较小段所在的相同起始地址处安装 bigget 块?
但你不应该放弃!你可以有创意。您可以想出拥有一个标头段的想法,您可以在其中存储有关实际有效负载段的信息。您可以使每个进程都遵守一些规则,例如:当它的 id(如header segment中某处所述)与已知的不匹配时重新附加有效负载段。
建议:我怀疑你知道这一点,但永远不要在共享区域内保留指向数据的指针,只保留 offset。
我希望你能利用我的胡言乱语。
在我看来,您可以为自己的目的编写自己的内存管理器。这个概念很简单:
- 您有一个大小为
N
字节的共享内存块; - 根据大小分配新的共享内存块
2*N
; - 将内存从一个块复制到另一个块;
- 释放旧的共享内存块;
- 将#2-4 包装成一些例程并使用它;
恐怕我们与此无关。这是如何std::vector
实现的。在void *realloc()
大多数情况下,将返回指向新内存块的指针(而不是扩展的旧块)。
在我看来,函数mremap的实现是为了执行你想要的。您只需在参数中精确说明旧大小和共享内存段的新大小。如果您添加标志 MREMAP_MAYMOV,它允许在需要时移动共享内存段(即,如果在旧共享内存段之后没有足够的可用空间)。
查看手册页: http: //man7.org/linux/man-pages/man2/mremap.2.html。