6

共有メモリに参照カウント オブジェクトがあるとします。参照カウントはオブジェクトを使用するプロセスの数を表し、プロセスはアトミック命令を介してカウントを増減する責任があるため、参照カウント自体も共有メモリにあります (オブジェクトのフィールドまたはオブジェクトのフィールドである可能性があります)。カウントへのポインターが含まれている可能性があります。この問題の解決に役立つ場合は、提案を受け付けています)。場合によっては、プロセスにバグがあり、カウントをデクリメントできないことがあります。どのプロセスがカウントを減少させていないかをできるだけ簡単に把握するにはどうすればよいでしょうか?

私が考えた解決策の 1 つは、各プロセスに UID (おそらく PID) を与えることです。次に、プロセスが減少すると、UID を参照カウントと一緒に保存されたリンク リストにプッシュします (リンク リストを選択したのは、CASを使用してヘッドにアトミックに追加できるためです)。デバッグする場合、共有メモリ内でまだ生きているオブジェクトのリンクされたリストを調べる特別なプロセスがあり、リストにないアプリの UID は、まだカウントを減らしていないアプリです。

このソリューションの欠点は、N がプロセスの数である場合、O(N) のメモリ使用量があることです。共有メモリ領域を使用するプロセスの数が多く、多数のオブジェクトがある場合、これはすぐに非常に高価になります。単一のプロセスを特定できなくても、部分的な固定サイズ情報を使用して、可能なプロセスのリストを何らかの方法で絞り込むことができ、デバッグを支援できる中途半端な解決策があるのではないかと思います。または、1 つのプロセスだけが減少していないときにどのプロセスが減少していないかを検出できた場合 (つまり、カウントの減少に失敗した 2 つ以上のプロセスの検出を処理できない場合)、それはおそらく大きな助けになるでしょう。

(この問題には、すべてのアプリケーションが同じライブラリを使用して共有メモリ領域にアクセスするようにするなど、より「人間的な」解決策がありますが、共有領域がバイナリ インターフェイスとして扱われ、すべてのプロセスが によって作成されたアプリケーションになるわけではありません。また、すべてのアプリが同じライブラリを使用している場合でも、1 つのアプリにライブラリの外部にバグがあり、カウントを減らすことができないような方法でメモリを破壊している可能性があります。 C/C++ ;)

編集:単一プロセスの状況では、制御できるため、RAII (C++) を使用できます。

4

5 に答える 5

8

これは、オブジェクトごとに追加の整数を 1 つだけ使用して行うことができます。

整数をゼロに初期化します。プロセスがオブジェクトの参照カウントをインクリメントすると、その PID を整数に XOR します。

object.tracker ^= self.pid;

プロセスが参照カウントをデクリメントすると、同じことが行われます。

参照カウントが 1 のままである場合、トラッカー整数は、それをインクリメントしたがデクリメントしなかったプロセスの PID と等しくなります。


これが機能するのは、XOR が交換可能 ( (A ^ B) ^ C== A ^ (B ^ C)) であるためです。したがって、プロセスが自身の PID を使用してトラッカーを偶数回 XOR する場合、それは XOR を使用するのと同じPID ^ PIDです。これはゼロであり、トラッカーの値は影響を受けません。

代わりに、符号なしの値 (オーバーフローではなくラップするように定義されている) を使用することもできます。つまり、使用カウントをインクリメントするときに PID を追加し、デクリメントするときに PID を減算します。

于 2010-02-08T08:12:35.217 に答える
1

リソース所有権の最も効率的な追跡システムは、参照ホルダーのリストはおろか、参照カウントさえも使用しません。それらは、メモリに存在する可能性のあるすべてのデータ型のレイアウトに関する静的情報、およびすべての関数のスタック フレームの形状に関する静的情報を持っているだけであり、すべてのオブジェクトには型インジケーターがあります。したがって、デバッグ ツールはすべてのスレッドのスタックをスキャンし、メモリ内のすべてのオブジェクトのマップとそれらが相互に参照する方法が得られるまで、オブジェクトへの参照を再帰的にたどることができます。もちろん、この機能を備えたシステムには自動ガベージ コレクションもあります。オブジェクトとスタック フレームのレイアウトに関するすべての情報を取得するには、コンパイラの助けが必要です。また、そのような情報は、すべての場合において C/C++ から実際に確実に取得することはできません (オブジェクト参照はユニオンなどに格納できるため)。

あなたの質問によると、「縮退」の場合、スタック上のローカル変数を除いて、プロセスの状態のすべて (またはほとんどすべて) が共有メモリに保持されます。その時点で、単一プロセスでのマルチスレッド プログラムとまったく同じになります。別の言い方をすれば、十分なメモリを共有するプロセスは、スレッドと見分けがつかなくなり始めます。

これは、質問の「複数のプロセス、共有メモリ」の部分を指定する必要がないことを意味します。参照カウントを使用しようとすると、誰もが直面するのと同じ問題に直面します。スレッドを使用する (または共有メモリを無制限に使用する; 同じこと) 人は、別の問題に直面します。2つを合わせると、痛みの世界になります。

一般的に言えば、可能であれば、可変オブジェクトをスレッド間で共有しないことをお勧めします。カウントは変更できるため、参照カウントを持つオブジェクトは変更可能です。つまり、(有効な) スレッド間で変更可能なオブジェクトを共有しています。

共有メモリの使用が複雑で GC に似たものが必要な場合は、両方の世界で最悪の事態が発生していると言えます。つまり、プロセス分離の利点がないプロセス作成のコストです。スレッド間で変更可能なオブジェクトを共有するマルチスレッド アプリケーションを (事実上) 作成しました。

ローカル ソケットは、プロセス間通信用の非常にクロスプラットフォームで非常に高速な API です。すべての Unice と Windows で基本的に同じように動作する唯一のものです。したがって、それを最小限のコミュニケーションチャネルとして使用することを検討してください。

ところで、参照を保持するプロセスでは一貫してスマート ポインターを使用していますか? それが、参照カウントを半分でも正しく行うための唯一の希望です。

于 2010-02-08T08:11:37.057 に答える
1

基本的に、共有メモリの共有状態は堅牢なソリューションではなく、堅牢にする方法を知りません。

最終的に、プロセスが終了すると、その非共有リソースはすべてオペレーティング システムによってクリーンアップされます。これは、スレッドの代わりにプロセス (fork()) を使用することの大きな利点です。

ただし、共有リソースはそうではありません。他の人が開いているファイルハンドルは明らかに閉じられておらず、 ...共有メモリ. 共有リソースは、それらを共有している最後のプロセスが終了した後にのみ閉じられます。

共有メモリに PID のリストがあるとします。プロセスはこのリストをスキャンしてゾンビを探すことができますが、PID が再利用されるか、アプリがクラッシュではなくハングするか、または...

各プロセス間でパイプまたはその他のメッセージ パッシング プリミティブを使用することをお勧めします (自然なマスター/スレーブ関係がある場合もあれば、すべてがすべてと対話する必要がある場合もあります)。次に、プロセスが終了したときにこれらの接続を閉じるオペレーティング システムを利用するため、そのイベントでピアにシグナルが送信されます。さらに、ping/pong タイムアウト メッセージを使用して、ピアがハングしたかどうかを判断できます。

プロファイリング後、これらのメッセージで実際のデータを送信するのが非効率的である場合は、オペレーティング システムがクリアする何らかの種類のストリームを介して制御チャネルを維持する限り、ペイロードに共有メモリを使用できます。

于 2010-02-08T07:30:04.093 に答える
0

以下を使用

int pids[MAX_PROCS]
int counter;

インクリメント

do
   find i such pid[i]=0  // optimistic
while(cas[pids[i],0,mypid)==false)
my_pos = i;
atomic_inc(counter)

デクリメント

pids[my_pos]=0
atomic_dec(counter);

したがって、このオブジェクトを使用するすべてのプロセスがわかります

あなたはMAX_PROCS十分に大きく、自由な場所をランダムに検索するので、プロセスの数が大幅に少ない場合MAX_PROCS、検索は非常に高速になります。

于 2010-02-08T08:44:41.390 に答える
0

自分で行うことに加えて、AQTime などの参照カウント memchecker を備えたツールを使用することもできます。

于 2010-02-08T20:13:07.210 に答える