Growing Boost.使用单个写入器的进程间内存映射文件

Growing Boost.Interprocess memory mapped file with single writer

本文关键字:进程 内存 映射 文件 Boost 单个写 Growing      更新时间:2023-10-16

我的问题是关于在单个写入器进程和多个读取器进程的上下文中使用Boost.Interprocess增加内存映射区域。是否可以使用作者的managed_mapped_file::grow,假设读者不更新地图大小的变化是可以接受的?我的假设是读者的地图将保持有效,然后当我需要他们从作者那里获取最新更改时,我可以使用更新的大小重新映射读者。这是对的吗?

文档的"不断增长的托管细分"部分指出:

创建受管理的细分

后,无法扩展受管理的细分。这个限制不容易解决:附加到托管段的每个进程都需要停止,通知新的大小,他们需要重新映射托管段并继续工作。[...]

这让我觉得我可以grow,只要我对读者没有立即更新很好。但是,文档继续说:

另一方面,Boost.Interprocess提供离线细分市场的增长。这是什么意思?如果没有进程映射托管分段,则可以增长分段。如果应用程序可以找到未附加进程的时刻,则可以增大或缩小以适应托管段。[...]managed_mapped_file还提供了类似的功能来增大或shrink_to_fit托管文件。请记住,在执行增长/收缩过程时,任何进程都不应修改文件/共享内存。否则,托管分段将损坏。

这让我觉得我不能做我想做的事情,但我不明白为什么它不起作用。

让我们仔细区分shared_memory_object(这确实是低技术且不强加的)和managed_shared_memory/managed_mapped_file(两者都使用segment_manager)。

您正在使用后者。


"假设读者可以接受不更新地图大小的变化":

我不明白这个假设如何成立。

受管段实质上构成一个辅助内存堆及其关联的控制结构。

控制结构包含详细信息(例如该"堆"的实际范围)是有意义的。由于控制结构位于共享内存中,因此它们也必须位于已映射到读取进程中的部分中。

更改内存段的大小将更改该控制结构中的值,该值从映射同一共享内存的所有进程中可见。这显然会对实际上没有足够的内存映射来满足新扩展数据块的进程造成严重破坏(充其量会导致页面错误)。

现在,我可以想象一个非常聪明的实现来规避对此类控制信息的需求(例如,具有哨兵值的经典自由阻止列表)。但我不认为 Boost Interprocess 会走这条路¹,你引用的文字强烈表明该设计不符合这种灵活性。

是否可以使用编写器的 managed_mapped_file::grow,假设读者可以接受不更新地图大小的变化?

不,这不行。

我的假设是读者的地图将保持有效,然后当我需要他们从作者那里获取最新更改时,我可以使用更新的大小重新映射读者。这是对的吗?

毫无疑问,/maps/会很好(取决于grow的实现方式,但我想我之前已经通过实验证实了这一点)。问题出在上面运行的segment_manager。这是要混淆的。

¹ 纯指尖