1

SysV 共有メモリを使用して、2 つのプロセスが相互に通信できるようにします。コードが複雑になりたくないので、セマフォを使用して共有メモリへのアクセスを同期する必要があるかどうか疑問に思いました。私の C/C++ プログラムでは、親プロセスが共有メモリから読み取り、子プロセスが共有メモリに書き込みます。セグメンテーション違反のような何らかのエラーを生成できるかどうかを確認するために、2 つのテスト アプリケーションを作成しましたが、生成できませんでした (Ubuntu 10.04 64 ビット)。2 つのプロセスが同じ共有メモリに while ループでノンストップで書き込みを行っても、エラーは発生しませんでした。

誰かがこの問題に関する経験を持っており、アクセスを同期するために本当にセマフォを使用する必要があるかどうか、または同期しなくても問題ないかどうかを教えてくれることを願っています.

ありがとう

4

6 に答える 6

6

ある種のミューテックスを使用しないと、何よりも中断に関連する奇妙で素晴らしいタイミング バグにさらされることになります。

共有メモリがプリエンプトされたときに、子供が共有メモリへの書き込みの途中であるとします。共有メモリは現在「悪い」状態にあります。その一部は子プロセスの 1 つの状態に関連し、残りはその前の状態に関連しています。また、子プロセスよりも先に親プロセスが再アクティブ化される可能性があります。次に、状態が破損しています。

短期的にはこれを回避できるかもしれませんが、後で奇妙なバグが見つかります。

于 2010-06-10T18:27:26.330 に答える
2

適切にマップされたメモリアドレスに書き込むことによって、いくつのプロセスが「同時に」実行しようとしても、セグメンテーション違反は発生しません。同期の目的は、むしろデータの一貫性を維持することです。

次の条件がすべて当てはまる場合、セマフォとミューテックス ロックを回避できます。

  1. 特定のアドレスに書き込むスレッドは 1 つだけです。

  2. 書き込まれるデータはアトミックです。つまり、1 回の I/O 操作で転送できます。char や int などの単純なものは、通常、転送時にアトミックです。多くの構造体、文字列、および配列は、多くの場合、複数の I/O サイズの要素で構成されているため、コピー時にアトミック操作ではありません。

  3. データ項目の有効性は、他のデータに依存しません。

  4. 古い逆参照を避けるために、データにアクセスするときにキーワード「volatile」を使用します。

上記のいずれかが満たされていない場合、データの一貫性と有効性を保証するには、何らかの同期を使用する必要があります。

于 2010-06-10T18:41:08.247 に答える
1

前述のように、セグメンテーション違反ではなく、データの整合性の問題です。

これが問題である場合は、次を使用します: パイプ - 実装する単純な IPC システムです。親で 6 行のコード、子でも同じです。

http://tldp.org/LDP/lpg/node11.html

于 2010-06-10T18:35:30.903 に答える
1

すべての優れた応答に加えて -boost::interprocessライブラリを見てください - C++ STL のようなコンテナーを共有メモリに保持するのに非常に便利です。SysV などではなく、Unixen の POSIX 共有メモリで実装されてshmem_open(3)います。これも興味があるかもしれません。

于 2010-06-10T19:02:31.043 に答える
0

アクセス許可を示すために 1 つのフラグを使用することをお勧めします。ライター スレッドがフラグを作成するように、書き込みが完了すると、ライター スレッドはそれをフラグ ++ にすることができます。リーダー スレッドも同じことを行います。このようにして、Mutex の使用とロックのオーバーヘッドを回避します。私はこれを使用しており、フラグを信頼しています--およびフラグ++はほとんどアトミックです:-)

于 2010-06-11T16:45:36.160 に答える
0

少し異なるアプローチを次に示します。リーダー/ライターが予期せ互いにプリエンプトしないことが保証できる場合は、それらの間で同期する必要はありません。

たとえば、Linux で、共有メモリにアクセスするすべてのプロセスに対してスケジューラ ポリシーSCHED_FIFO( を参照sched_setscheduler(2)) を使用する場合、およびそれらが同じリアルタイム優先度で実行されている場合、およびそれらがすべて同じ CPU コアにロックされている場合 (マルチコア システム上)。次に、リーダーが実行中の場合、条件で待機するか、タイマーでスリープすることを選択するまで、リーダーは実行中の唯一のプロセスになります。ライターが待機していた何らかの状態から復帰した場合でも、読み取り中に、スケジューラーはリーダーが完了するまでライターを実行させません。

于 2010-06-10T21:27:08.063 に答える