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を使用します。このライブラリはこの機能を公開します。

編集:ここであなたがする必要があるいくつかの変更があります:

この例では、共有メモリ ブロックから割り当てるアロケータが既に定義されています。これをmapおよびに渡す必要がありますqueue。これは、定義を変更する必要があることを意味します。

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); 

私はそれがトリックを行うべきだと思います。queue注: 2 つのアロケータ ( 用と 用に 1 つ)を提供する必要がありますmap。同じセグメント マネージャから 2 つのアロケータを構築できるかどうかはわかりませんが、なぜできないのかわかりません。

于 2012-08-31T07:22:06.753 に答える
3

これは注意が必要です。まず、カスタム アロケータが必要です。Boost Interprocess には 1 つあり、私はそれから始めます。正確な例では、これで十分かもしれませんが、より一般的には、すべてのサブタイプが共有メモリも使用するようにする必要があります。したがって、文字列からマップする場合、その文字列にはカスタム アロケータも必要になります。つまり、それは とは異なる型を持ちstd::stringstd::string(ただし、2 つのイテレータを使用してコンストラクタ、例:

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 オブジェクトの一貫性を維持することです。基本的に、プロセスの 1 つが不適切な時点でクラッシュすると、他のプロセスに次の 2 つの大きな問題が残ります。

  • ロックされたミューテックス (トリッキーな PID からミューテックスへのマッピング、堅牢なミューテックス (利用可能な場合)、時限ミューテックスなどを使用して解決できます。

  • 不整合な状態の STL オブジェクト (たとえば、ererase() プロシージャ中の半更新されたマップ構造)。一般に、これはまだ回復可能ではありません。共有メモリ領域内のオブジェクトを最初から破棄して再構築する必要があります (おそらく他のすべてのプロセスも強制終了します)。アプリで考えられるすべての外部信号を傍受しようとするかもしれませんが、すべてがうまくいき、プロセスが悪い瞬間に失敗しないことを願っています。

システムで共有メモリを使用することを決定するときは、このことを念頭に置いてください。

于 2015-10-01T23:57:48.583 に答える