1

我们的应用程序依赖于可加载为 .so 文件的外部第 3 方提供的配置(包括自定义驾驶/决策功能)。

独立地,它使用一块共享内存与外部 CGI 模块合作,其中几乎所有的易失性状态都被保存下来,以便外部模块可以读取它并在适用的情况下对其进行修改。

问题是 CGI 模块也需要来自 .so 的大量永久配置数据,并且主应用程序在两个内存区域之间执行大量完全不必要的复制以使数据可用。这个想法是让整个共享对象加载到共享内存中,并使其直接可供 CGI 使用。问题是:如何?

  • dlopen 和 dlsym 不提供任何工具来指定加载 SO 文件的位置。
  • 我们尝试了 shmat()。它似乎只在某些外部 CGI 实际尝试访问共享内存之前才有效。然后指向的区域看起来就像从未共享过一样私密。也许我们做错了什么?
  • 在每个需要它的脚本中加载 .so 是不可能的。结构的庞大规模与调用频率有关(一些脚本每秒调用一次以生成实时更新),而这是一个嵌入式应用程序,使其无法运行。
  • 简单地将 .so 放入 shm 中的 memcpy() 也不好——一些结构和所有函数都通过指针相互连接。
4

4 回答 4

4

使用共享内存时要记住的第一件事是,相同的物理内存很可能作为不同的地址映射到两个进程的虚拟地址空间中。这意味着如果在数据结构中的任何地方使用指针,它们都会导致问题。一切都必须使用索引或偏移量才能正常工作。要使用共享内存,您必须清除代码中的所有指针。

加载 .so 文件时,仅加载 .so 文件代码的一份副本(因此称为共享对象)。

fork也可能是你这里的朋友。大多数现代操作系统都实现了写时复制语义。这意味着当你fork,当一个进程写入给定的数据段时,你的数据段只会被复制到单独的物理内存中。

于 2010-01-25T11:56:33.887 回答
2

我想最简单的选择是使用 Neil 已经提出的内存映射文件。如果此选项不能很好地填充,替代方法是定义专用分配器。这是一篇关于它的好论文:在共享内存中创建 STL 容器

还有优秀的 Ion Gaztañaga 的Boost.Interprocessshared_memory_object以及相关功能。Ion 已向 C++ 标准化委员会提出了未来 TR 的解决方案:Memory Mapped Files And Shared Memory For C++ ,这可能表明值得考虑的解决方案。

于 2010-01-30T06:58:26.043 回答
2

正如您所发现的,将实际的 C++ 对象放在共享内存中非常非常困难。我强烈建议您不要那样做——将需要共享的数据放在共享内存或内存映射文件中要简单得多,而且可能更健壮。

于 2010-01-25T09:58:30.950 回答
0

您需要实现对象的序列化序列 化函数将您的对象转换为字节,然后您可以在 SharedMemory 中写入字节并让您的 CGI 模块将字节反序列化回对象。

于 2010-01-29T12:41:08.250 回答