2010-01-25 244 views
1

我们的应用程序依赖于外部,第三方提供的配置(包括自定义驱动/决策功能),可加载的.so文件。如何在共享内存中得到共享对象

独立地,它使用共享存储器,其中几乎所有的挥发性状态被保持的组块的外部CGI模块,从而使外部模块可以读取它并修改它适用配合。

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

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

回答

2

我想最简单的选项是使用内存映射文件,什么尼尔提出了。如果这个选项填不好,另一种方法是可以定义专用的分配器。这里有一个关于它的好文章:Creating STL Containers in Shared Memory

还有优秀的IonGaztañaga的Boost.Interprocess库与shared_memory_object和相关功能。Ion已经向未来TR的C++标准化委员会提出了解决方案:Memory Mapped Files And Shared Memory For C++ 可能表明这是值得考虑的解决方案。

+0

虽然它不直接回答我的问题,但我猜这是最接近它。我还没有看到一个有用的调用shmat()与第二个参数不同于NULL。 – 2010-01-31 00:01:43

+0

将它留空,并让系统决定正在存储的内存段的位置,并将其地址返回给您。 – mloskot 2010-01-31 00:18:57

2

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

3

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

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

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

0

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

+0

恐怕我无法序列化C函数。 – 2012-02-10 12:49:23