如何在共享内存中获取共享对象

时间:2010-01-25 09:53:56

标签: c++ c linux shared-memory shared-objects

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

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

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

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

4 个答案:

答案 0 :(得分:3)

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

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

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

答案 1 :(得分:2)

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

答案 2 :(得分:2)

我认为最简单的选择是使用内存映射文件,Neil已经提出了什么。如果此选项填充不好,则可以选择定义专用分配器。这是一篇关于它的好文章:Creating STL Containers in Shared Memory

还有出色的IonGaztañagaBoost.Interprocess图书馆shared_memory_object和相关功能。 Ion为未来的TR提出了C ++标准化委员会的解决方案:Memory Mapped Files And Shared Memory For C++ 可能表明值得考虑的解决方案。

答案 3 :(得分:0)

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