web-dev-qa-db-ja.com

C / C ++で記述されたアプリケーション間でメモリを共有する方法

ロボット工学の制御のために、C/C++で書かれたプログラムを実行しています。基本的に、3つの異なるプログラムが同時に実行され、共有メモリを介して通信します。私が見つけた周りのグーグルリンギングは、vxWorksやboostライブラリのプロセス間ヘッダー( Boostのドキュメント:プロセス間でのメモリの共有 )のようなものだと思います。

今、私は実装を見たくありません、上のリンクを読むことができます。しかし、boostライブラリがこれをどのように実行するかについて、頭を動かすことはできません。つまり、1つのアプリケーションがメモリを割り当て、他のアプリケーションがそのメモリにアクセスしますが、それらはどのように通信しますか?これを行うのは危険ではありませんか?

9
cauchy

しかし、boostライブラリがこれをどのように実行するかについて、頭を動かすことはできません。

ブーストプロセス間メカニズムには、機能するために3つの必要なコンポーネントがあります。

  1. メモリマップファイル:メモリマップファイルを作成し、boost.interprocessアロケーターに渡す必要があります。このアロケーターは、ファイルのチャンクを取得し、それらがstd :: allocatorによって返されたかのように使用します。マッピングは、メモリーがインプロセス固有のメモリーと互換性があるように適用されます。

  2. boost.interprocessコンテナー;この種類のコンテナーは、アロケーターによって返されたメモリを使用し、インターフェイスのようなstd :: container(begin/end/size/Push_backなど)を提供します。

  3. 同期メカニズム;これは任意のプロセス間ミューテックスにすることができ、データアクセスの競合状態を防ぐために使用する必要があります。

つまり、1つのアプリケーションがメモリを割り当て、他のアプリケーションがそのメモリにアクセスしますが、それらはどのように通信しますか?これを行うのは危険ではありませんか?

割り当てられたメモリは、実際には共有メモリマップファイルです。通信は間接的であり、両方のアプリケーションが必要に応じてデータを設定または読み取ります。安全性は、プロセス間同期プリミティブを使用することによってもたらされます。

11
utnapistim

共有メモリはIPCの全体像ではなく、そのデータ受け渡しメカニズムですが、一部のデータが更新されており、読み取り可能であることを他のプロセスに通知する何らかの方法が必要です。これをどのように行うかはあなた次第です。通常、OSミューテックスまたはイベントオブジェクトを使用します。各プロセスはこれが設定されるのを待機し、アプリケーションの書き込みは書き込みが完了すると設定します。次に、他のプログラムのスレッドが起動して読み取ります。

または、ポーリングして、定期的にデータを読み取り、データが更新されたときに変化する値を求めます(例:増分カウンター)。

5
gbjbaanb

Boostは、ファイルのメモリマッピングを使用します。

UNIXとWindowsはどちらも、この目的のためだけに、通常のファイルシステムには存在しないファイルの作成をサポートしています。

次に、別のスレッドがメモリにアクセスする場合と同様に、そのメモリへのアクセスを同期する必要があります。同時読み取りは同期せずに発生する可能性がありますが、1つのプロセスが書き込みを行い次第、他のプロセスがアクセスできないようにする必要があります。

ロックレス同期が必要な場合でも、共有メモリでのアトミック操作は可能です。

4
ratchet freak

CとC++は異なる言語であることに注意してください。

共有メモリは純粋に標準C11、またはC++ 11(標準で定義されていないため)、または C + +14n369 ドラフトで、おそらく公式の標準では、マルチスレッド以外の共有メモリについては触れられていません)。したがって、共有メモリを取得するには追加のライブラリが必要です。ただし、一部のオペレーティングシステムは共有メモリをサポートしています。そのため、既存のオペレーティングシステムサービスの上に構築された共有メモリを提供するいくつかのライブラリが存在します。 [〜#〜] poco [〜#〜] フレームワークライブラリ(OS固有の詳細を抽象化する)の使用を検討することもできます。

Linux(およびおそらくPOSIX)の場合は、 shm_overview(7) を調べます。同期する必要があるので、 sem_overview(7) も参照してください。

VXWorks(それは私にはわかりませんが、ググった)には VxMP があります

実際に何が起こっているのかを注意深く理解する必要があります。 (C++クラスではなく)単純な古いデータstruct- sのみを共有する必要があり、アドレス(各プロセスが共通の共有メモリセグメントに対して異なるアドレスを取得する可能性があります)と同期について非常に注意する必要があります。

または、スレッドを使用します。 C++ 11標準では スレッドライブラリ が定義されていることに注意してください。

共有メモリは依然として単なるメモリです。ミューテックス、スピンロック、またはその他の同期プリミティブをそこに配置し、スレッドがそれらのプリミティブを使用して、それらに見えるメモリへのアクセスを同期するのとまったく同じように、共有メモリへのプロセスのアクセスを同期することができます。

実際の違いは次のとおりです。

  1. スレッドはすべてのメモリと同じアドレス空間を共有するため、生のポインタがそれらに対して機能します。プロセス間で共有されるメモリはまったく同じように機能しますが、プロセスごとに異なるアドレスにマッピングされる可能性があるため、プロセス間で生のポインタを単純に渡すことはできません

    • NB。これは、仮想メソッドの実装の詳細、実行時の型情報、およびその他のC++メカニズムにノックオン効果をもたらします。共有メモリに仮想メソッドや動的キャストを含まない、単純に初期化可能な(プレーンな古いデータ)タイプに固執し、typeidを使用しないでください。問題はありません。
  2. 一部の同期プリミティブは、プロセス間で正しく機能するために特別なフラグまたは属性を必要とする場合があります(PTHREAD_PROCESS_SHARED POSIXスレッドmutexの属性など)。これは実際にはメモリと同期自体とは関係ありませんが、スリープしているウェイターをウェイクアップするために必要なカーネルとスケジューラの相互作用が原因です。


そう:

しかし、彼らはどのように通信しますか?

異なるスレッドが通信するのと同じ方法で、上記の警告を可能にします

これを行うのは危険ではありませんか?

はい、スレッドが共有メモリを介して通信するのと同じように、プロセスが共有メモリを介して通信することは危険であり、スレッドはmakeと同等(または同一)の同期が必要です。

3
Useless