2

パフォーマンス上の理由から共有メモリを使用するプログラムを作成しています(代替手段としてのソケットとパイプが評価されており、これらは私のタスクには十分な速度ではありません。一般的に、コピーを含むIPCメソッドは遅すぎます)。共有メモリ領域では、固定サイズの多くの構造体を書いています。構造体を共有メモリに書き込むためのプログラムが1つあり、そこから読み取る多くのクライアントがあります。ただし、クライアントが書き込む必要のある各構造体のメンバーは1つです(参照カウント。アトミックに更新されます)。他のすべてのメンバーは、クライアントに対してのみ読み取る必要があります。

クライアントはその1つのメンバーを変更する必要があるため、共有メモリ領域を読み取り専用としてマップすることはできません。ただし、他のメンバーをいじくり回してはいけません。これらのプログラムはC ++で記述されているため、メモリが破損する可能性があります。理想的には、あるクライアントが別のクライアントをクラッシュさせることは可能な限り困難である必要があります。私はバグのあるクライアントについてのみ心配しており、悪意のあるクライアントについては心配していないので、不完全な解決策は許可されています。

ヘッダーでconstとして使用するメンバーを宣言することで、クライアントによる上書きを阻止することができますが、それでもメモリの破損(バッファオーバーフロー、不正なキャストなど)による上書きを防ぐことはできません。カナリアを挿入することはできますが、それをチェックするための費用を常に支払う必要があります。

参照カウントメンバーを直接保存する代わりに、構造体を読み取り専用のマップされたページに保持しながら、実際のデータへのポインターを別のマップされた書き込み専用ページに保存することができます。これは機能します。ポイントされたデータに書き込もうとすると、OSによってアプリケーションが強制的にクラッシュしますが、ロックフリーアルゴリズムを書き込もうとすると、間接ストレージが望ましくない場合があります。これは、別のレベルの間接参照に従う必要があると、何かができるかどうかが変わる可能性があるためです。アトミックに行われます。

メモリの小さな領域にマークを付けて、それらを書き込むとアプリが爆発するようにする方法はありますか?一部のプラットフォームにはハードウェアウォッチポイントがあり、インラインアセンブリでそれらの1つをアクティブ化できるかもしれませんが、32ビットx86では一度に4つに制限され、それぞれが制限されているため、構造体の一部しかカバーできませんでした4バイトまで。また、プログラムをデバッグするのが面倒になります;)

編集:私はこのかなり目を見張るような紙を見つけましたが、残念ながら、ECCメモリと変更されたLinuxカーネルを使用する必要があります。

4

3 に答える 3

6

OSレベルでそのように数ビットを読み取り専用にすることは不可能だと思います。

今私が思いついたのは、あなたが提案したように、参照カウントを別のページに置くことができるということです。構造体が共通のサイズであり、すべてが順次メモリ位置にある場合は、構造体内にポインタを置くのではなく、ポインタ演算を使用して構造体ポインタから参照カウントを見つけることができます。これは、ユースケースへのポインタを持つよりも優れている場合があります。

long *refCountersBase;//The start address of the ref counters page
MyStruct *structsBase;//The start address of your structures page

//get address to reference counter
long *getRefCounter(MyStruct *myStruct )
{
    size_t n = myStruct - structsBase;
    long *ref = refCountersBase + n;
    return ref;
}
于 2010-03-20T22:19:57.733 に答える
1

例外から回復するSIGSEGVのシグナルハンドラを追加する必要がありますが、これは特定のアドレスに対してのみです。開始点は、http://www.opengroup.org/onlinepubs/009695399/basedefs/signal.h.htmlおよびOSの対応するドキュメントです。

編集:書き込みアドレスが実際にOKの場合は書き込みと戻りを実行し、例外を伝播する場合は前の例外ハンドラー(例外ハンドラーをインストールしたときに取得するポインター)を末尾呼び出しすることが必要だと思います。しかし、私はこれらのことを経験していません。

于 2010-03-21T03:45:10.517 に答える
1

ページの粒度未満で読み取り専用を適用することは聞いたことがないので、各構造体を2ページに配置できない限り、その方向に不運になる可能性があります。構造体ごとに2ページの余裕がある場合は、一方のページに参​​照カウントを設定し、もう一方のページを読み取り専用にすることができます。

ヘッダーを使用するだけでなく、APIを作成することもできます。クライアントにAPIの使用を強制すると、ほとんどの破損の問題が解消されます。

別のページではなく参照カウントを使用してデータを保持すると、データの局所性が向上し、キャッシュのパフォーマンスが向上します。

リーダーに問題があり、参照カウントを適切に更新できない可能性があることを考慮する必要があります。また、ライターが更新を完了できない場合もあります。これらに対処するには、追加のチェックが必要です。このようなチェックをAPIと組み合わせることができます。ある種の整合性チェックのパフォーマンスへの影響を測定することは、実験する価値があるかもしれません。チェックサムを保持するのに十分な速さである可能性があります。これはadler32のような単純なものです。

于 2010-03-21T04:20:53.180 に答える