8

オペレーティング システムが、同じ DLL/共有ライブラリをロードする複数の無関係なプロセスを処理する方法を理解しようとしています。私が関心を持っている OS は Linux と Windows ですが、それほどではありませんが Mac も同様です。私の質問に対する答えは、すべてのオペレーティング システムで同じであると思います。

私は明示的なリンクに関して特に興味がありますが、暗黙のリンクについても知りたいです。両方の答えも同じになると思います。

これは、Windows に関してこれまでに見つけた最良の説明です。

「システムは、ロードされたすべてのモジュールのプロセスごとの参照カウントを維持します。LoadLibrary を呼び出すと、参照カウントがインクリメントされます。FreeLibrary または FreeLibraryAndExitThread 関数を呼び出すと、参照カウントが減少します。システムは、参照カウントがゼロに達するか、プロセスが終了したときにモジュールをアンロードします (参照カウントに関係なく)」- http://msdn.microsoft.com/en-us/library/windows/desktop/ms684175%28v=vs.85%29.aspx

しかし、いくつかの疑問が残ります。

1.) 参照カウントを使用する代わりに、関連のないプロセスが同じ DLL を重複してロードしますか (つまり、DLL がメモリ内に複数存在します)? (IE、私が理解していると思うように、各プロセス独自の「アドレス空間」に)

プロセスが終了するとすぐにDLLがアンロードされると、まったく同じDLLを使用する他のプロセスがメモリに重複してロードされると思われます。そうでない場合、システムは参照カウントを無視できません。

2.) それが本当なら、同じプロセスで複数回ロードするときに DLL をカウントする参照のポイントは何ですか? 同じ DLL を同じプロセスに 2 回ロードするポイントは何でしょうか? 私が思いつく唯一の実行可能な理由は、EXE が 2 つの DLL を参照し、DLL の 1 つが他の DLL を参照している場合、同じライブラリに対して少なくとも 2 つの LoadLibrar() 呼び出しと 2 つの FreeLibrary() 呼び出しがあるということです。

ここで自分の質問に答えているように見えることはわかっていますが、仮定しているだけです。確かに知りたいです。

4

1 に答える 1

6

共有ライブラリまたは DLL は、コード部分に対して 1 回ロードされ、書き込み可能なデータ部分に対して複数回ロードされます [おそらく「コピー オン ライト」を介して。パーツが書き込まれると、元の値から変更されていない限り、すべての DLL で同じパーツを使用できます]。

ただし、DLL が複数回ロードされる可能性があります。DLL がロードされると、コードが開始されるベースアドレスがロードされます。たとえば、2 つの DLL を使用しているプロセスがある場合、以前の読み込みのために同じベースアドレスを使用している場合 [これを使用している他のプロセスが両方を使用していないため]、DLL の 1 つを使用する必要があります。別のベースアドレスで再度ロードされます。ほとんどの DLL では、これはかなり珍しいことです。しかし、それは起こる可能性があります。

すべてのロードを参照カウントするポイントは、モジュールを安全にアンロードできるタイミング (参照カウントがゼロのとき) をシステムが認識できるようにすることです。システムに 2 つの異なる部分があり、どちらも同じ DLL を使用する必要があり、両方がその DLL をロードする場合、システムの最初の部分が DLL を閉じたときにシステムをクラッシュさせたくありません。しかし、システムの 2 番目の部分が DLL を閉じたときに DLL がメモリに残ることも望ましくありません。メモリの無駄になるからです。[このアプリケーションがサーバー上で実行されるプロセスであり、新しい DLL が毎週サーバーからダウンロードされると想像してください。したがって、毎週、「最新の」DLL (別の名前を持つ) がロードされます。数か月後、メモリ全体がこのアプリケーションの「古くて使用されていない」DLL でいっぱいになります]。LoadLibrary呼び出し、メインの実行可能ファイルがまったく同じ DLL をロードします。FreeLibrary繰り返しますが、閉じるには2 つの呼び出しが必要です。

于 2013-06-28T23:31:12.250 に答える