14

我有以下代码模式:

class A {
    double a, b, c;
    ...
};

class B {
    map<int, A> table; // Can have maximum of MAX_ROWS elements.
    ...
};

class C {
    B entries;
    queue<int> d;
    queue<int> e;
    ...
};

现在我想将一个 C 类型的对象存储在共享内存中,以便不同的进程可以追加、更新和读取它。我怎样才能做到这一点?(注意:我知道如何在共享内存中存储一​​个具有固定大小的简单 C 数组。另外,请记住 B.table 可能有任意条目。

4

3 回答 3

17

使用boost::interprocess,这个库公开了这个功能。

编辑:这里有一些你需要做的改变:

该示例已经定义了一个从共享内存块分配的分配器,您需要将其传递给mapqueue。这意味着您必须更改定义:

class B
{
  map<int, A, less<int>, MapShmemAllocator> table;

  // Constructor of the map needs the instance of the allocator
  B(MapShmemAllocator& alloc) : table(less<int>(), alloc)
  { }
}

对于queue,这个稍微复杂一点,因为它实际上只是一个适配器,所以需要将真正的实现类作为模板参数传入:

typedef queue<int, deque<int, QueueShmemAllocator> > QueueType;

现在您的班级C略有变化:

class C
{
  B entries;
  QueueType d, e;

  C(MapShmemAllocator& allocM, QueueShmemAllocator& allocQ) : entries(allocM), d(allocQ), e(allocQ)
  { }
}

现在从段管理器中,C使用分配器构造一个实例。

C *pC = segment.construct<C>("CInst")(allocM_inst, allocQ_inst); 

我认为这应该可以解决问题。注意:您将需要提供两个分配器(一个 forqueue和一个 for map),不确定是否可以从同一个段管理器构造两个分配器,但我不明白为什么不能。

于 2012-08-31T07:22:06.753 回答
3

这可能很棘手。对于初学者,您需要一个自定义分配器:Boost Interprocess 有一个,我将从它开始。在您的确切示例中,这可能就足够了,但更一般地说,您需要确保所有子类型也使用共享内存。因此,如果您想从一个字符串映射,该字符串还需要一个自定义分配器,这意味着它具有与 不同的类型std::string,并且您不能从一个std::string(但您可以使用两个迭代器构造函数,例如:

typedef std::basic_string<char, std::char_traits<char>, ShmemAllocator> ShmemString;
std::map<ShmemString, X, std::less<ShmemString>, ShmemAllocator> shmemMap;

访问如下:

shmemMap[ShmemString(key.begin(), key.end())] ...

当然,您定义的进入映射的任何类型也必须使用共享内存进行任何分配:Boost Interprocess 有一个 offset_ptr这可能会有所帮助。

于 2012-08-31T08:32:04.247 回答
2

在共享内存中构建和使用 STL 对象并不棘手(尤其是使用 boost::interprocess 包装器)。当然,您还应该使用同步机制(对于 boost 的 named_mutex 也不是问题)。

真正的挑战是在共享内存中保持 STL 对象的一致性。基本上,如果其中一个进程在错误的时间点崩溃,它会给其他进程留下两个大问题:

  • 锁定的互斥锁(可以使用棘手的 PID 到互斥锁映射、强大的互斥锁(只要可用)、定时互斥锁等来解决。

  • 处于不一致状态的 STL 对象(例如,erase() 过程中的半更新映射结构)。通常,这还无法恢复,您需要从头开始销毁并重新构建共享内存区域中的对象(可能还会杀死所有其他进程)。您可能会尝试在您的应用程序中拦截所有可能的外部信号并交叉手指希望一切顺利并且处理永远不会在糟糕的时刻失败。

在决定在系统中使用共享内存时请记住这一点。

于 2015-10-01T23:57:48.583 回答