2

この質問が以前に回答されている場合は申し訳ありません。ただし、同様の質問はすべて、DLL 内のグローバル変数または静的変数とそれらの共有に関連しているようです。

2 つの個別のアプリケーション間で dll の 1 つのインスタンスを共有することは可能ですか?

2 つのアプリケーション (appA、appB) と DLL (theDLL) があります。

appA が theDLL の関数を呼び出して、ヒープ上に変数を作成し、それを theDLL に格納できるかどうかを確認しています。後で、appB を theDLL に接続して、以前に作成した変数にアクセスできるようにしたいと考えています。繰り返しますが、この回答が dll の静的およびグローバル変数と同じである場合は申し訳ありません。

ここにいくつかの疑似コードがあります:

(DLL)

class VariableHolder
{
 public:
     void StoreVariable(int x)
     {
        mInt = new int(x);
     }

     int GetVariable()
     {
        return mInt;
     }
 private:
     int mInt;
}

(アプリA)

int main()
{
    ...
    (assuming we got access to a VariableHolder singleton created in theDLL)
    theVarialbeHolder.StoreVariable(5);
    ... 
}

(appB)

int main()
{
    ...
    (assuming we got access to a VariableHolder singleton created in theDLL)
    if (theVarialbeHolder.GetVariable() == 5)
    {
        cout << "Hurray, how did you know?";
    }
    ... 
}
4

6 に答える 6

3

最新のオペレーティングシステムのほとんどすべての共有ライブラリは、共有の読み取り専用の実行可能ファイルとデータページによって実装され、特定のライブラリを使用するプロセスのアドレス空間に同時にマップされます。ただし、Windowsでは(ほとんどのUnixシステムとは対照的に)、この共有をDLLの読み取り/書き込みデータセグメントに拡張することもできるため、DLLにグローバル変数を設定して、DLLがロードされているすべてのイメージ間で共有することができます。これを実現するには、2段階のプロセスが必要です。最初に、共有変数を新しい名前付きデータセクションに配置するようにコンパイラーに指示します。

#pragma data_seg (".myshared")
int iscalar = 0;
int iarray[10] = { 0 };
#pragma data_seg ()

.bssこれらの変数をすべて静的に初期化することが重要です。そうしないと、代わりにセクションに入れられてしまいます。.myshared次に、オプションを使用して、読み取り/書き込み属性を共有するセクションを作成することをリンカに指示する必要があり/SECTION:.myshared,RWSます。

このメカニズムは、名前付き共有メモリオブジェクトを作成してバインドするよりもはるかに簡単ですが、静的に割り当てられたグローバル変数のみを共有できます。ヒープはプロセス専用であるため、ヒープ上のデータを共有するために使用することはできません。より複雑なものについては、共有メモリマッピングを使用する必要があります。つまり、MSDNページに示されているように、H2CO3からの回答にリンクされています。

于 2012-08-16T08:29:52.193 に答える
3

2 つのプロセスのアドレス空間が異なるため (カーネルによって作成された仮想プロセスであるため)、これはまったく不可能です。そのため、一方の有効なポインターは他方では機能しません。ただし、共有メモリを使用して、プロセス間で生のスカラー データ (文字列、整数) を転送できます。その方法は次のとおりです。

于 2012-08-15T05:28:09.860 に答える
3

はい、これは共有メモリを使用して可能です。ただし、共有 DLL を使用する必要はありません。

操作に応じて、アプローチは多少異なります。

  • Windows では、メモリにマップされた共有ファイルが使用されます (名前付き共有メモリの作成 を参照)。

  • Linux と Unix には、System V IPC などの共有メモリ領域を作成するための直接関数があります。グーグルで検索してください。

于 2012-08-15T05:50:58.967 に答える
1

これは不可能です。DLL は 2 プロセスで共有できますが、データは共有できません。共有されるのはコードまたはプログラム イメージ (つまり、ロジックまたは命令) であり、データではありません。すべての Dll は、それをロードするプロセスの仮想アドレス空間にマップされるため、データはプロセスのデータ セクション上にあるか、関数に対してローカルである場合はスタック上にあります。プロセスが実行中の場合、他のプロセス データのアドレスは表示されません。

仮想メモリとメモリ管理ユニット(MMU)の仕組みを読み取る必要があります。OS、CPU、MMUが連携してそれを可能にします。これを行う信頼できる方法は、プロセス間通信です。各プロセスが仮想アドレスの形式でデータのコピーを持っている共有メモリを使用できますが、最終的には実メモリの同じ場所、つまり実アドレスにマップされます。OSがそれを可能にします。

于 2012-08-15T05:47:35.473 に答える
0

共有メモリを使用する必要があります(上記のとおり)。

Boostインタープロセスライブラリを使用することをお勧めします。共有メモリに関するドキュメントを参照してください-プロセス間の共有メモリ

于 2012-08-15T06:01:18.447 に答える
0

これは @ H2CO3 が指摘したように、アドレス空間が異なるため不可能です。

ただし、問題から、そのDLLまたはサービスの周りに代理プロセスが必要であり、その後、異なるプロセスがその代理プロセス/exeに接続して共有メモリを使用できるようです。

于 2012-08-15T05:31:31.403 に答える