如何实现动态共享内存大小调整?

时间:2015-06-03 20:28:48

标签: c memory-management resize shared-memory mmap

目前我使用shm_open获取文件描述符,然后每当我想要向共享内存添加新缓冲区时使用ftruncate和mmap。每个缓冲区都单独用于其自身目的。

现在我需要做的是随意调整缓冲区大小。 此外,munmap缓冲区再次重用可用空间。

我能解决第一个问题的唯一解决方案是:ftuncate(file_size + old_buffer_size + extra_size),mmap,将数据复制到新缓冲区中,然后对原始数据进行munmap。这看起来对我来说非常昂贵,可能有更好的方法。它还需要每次都删除原始缓冲区。

对于第二个问题我甚至没有一个糟糕的解决方案,我显然无法在每次移除缓冲区时移动内存。如果我跟踪可用内存并尽可能地使用它,它将减慢分配过程,并留下我之间尚未使用的点点滴滴。

我希望这不会太混乱。 感谢

2 个答案:

答案 0 :(得分:3)

据我所知,你需要增长(或缩小)现有的内存映射。 在linux下共享内存实现为一个文件,位于/ dev / shm内存文件系统中。此文件中的所有操作与常规文件(和文件描述符)上的操作相同。

如果你想增长现有的映射,首先使用ftruncate扩展文件大小(如你所写),然后使用mremap将映射扩展为所请求的大小。

如果存储指向此区域的指针,则可能需要更新这些指针,但首先尝试使用0标记进行调用。在这种情况下,系统会尝试将现有映射增加到请求的大小(如果没有与其他保留的内存区域冲突),并且指针仍然有效。

如果以前的选项不可用,请使用MREMAP_MAYMOVE标志。在这种情况下,系统会重新映射到其他位置,但大多数情况下它会有效地完成(系统不会应用任何副本。)然后更新指针。

收缩是相同的,但顺序相反。

答案 1 :(得分:3)

我为此目的编写了一个开源库: rszshm - resizable pointer-safe shared memory

引用说明页面:

  

为了适应调整大小,rszshm首先映射一个大的私有noreserve   地图。这用于声明地址范围。共享文件映射   然后覆盖跨度的开始。后来要求延长   映射覆盖更多的跨度。试图超越结束   跨度返回错误。

我通过在原始地址调用带有MAP_FIXED的mmap并使用新大小来扩展映射。