私は MinGW の開発者ではありませんが、あなたの質問は非常に一般的であり、DLL の作成方法にはあまり依存していません。このような問題は、通常、次の 3 つの手法を使用して解決できます。
- DLL の一意のベース アドレスの選択
- DLL と exe のバインド (アプリケーションのインストール中)
- DLL 遅延読み込み手法の使用
- 一部のDisableThreadLibraryCallsの呼び出しの読み込み時間を少し改善します
DLL_PROCESS_ATTACH
DllMain
使用できるリンカーまたはその他のツールの正確なスイッチは、開発環境によって異なります。
問題を理解するには、実行可能ファイルまたは DLL がどのように読み込まれるかを知っておく必要があります。まず、EXE または DLL がメモリにマップされます。EXE/DLL を指すメモリ マップド ファイル(セクション) が作成されます。そのため、アクセスが EXE/DLL ファイルに対応するプロセスで、いくつかのアドレスが得られます。DLL をリンクすると、ベース アドレスを選択できます。アドレスがプロセスのアドレス空間で使用されていない場合、何も行われません。コードの最初の行が使用される場合 (DLL から何らかの関数を呼び出す場合)、使用されたアドレスに近い 8K のメモリのページがファイルからメモリにロードされます。2 つのプロセスが同じ DLL を使用する場合、コードの物理メモリは共有されます。プロセス間。初期化された変数を保持していても、変数を含むページは変数の最初の変更まで共有されます。変更すると、変更を行ったプロセスのメモリのページのコピーが作成されます。
プロセスで DLL がロードされた後、DLL から使用される関数の実際のアドレスを含めるために、呼び出し元 (EXE など) のいくつかの小さな部分を変更する必要があります。別の DLL の関数を使用する DLL についても同じことが行われます。
すべてが完璧に聞こえますが、DLL のコンパイル中にリンカー オプションを設定しない場合 (--image-base
または--enable-auto-image-base
リンカー オプションを使用しない場合)、すべての DLL が同じベース アドレス (リンカーの既定値) を持つことになります。したがって、最初の DLL をそのアドレスにロードできます。同じ (または重複したアドレス) にリンクされている 2 番目の DLL のロード中に、DLL の再配置が行われます。再配置中に DLL のコードが変更されるため、1) DLL のロードが遅くなります 2) プロセスでコードの変更されたコピーが作成されます (これには DLL によって使用されるメモリが含まれます) 3) 変更されたコピーDLL の複数のインスタンス間で共有されることはありません (すべてのインスタンスが同じ方法で変更される場合でも)。
まず、たとえばProcess Explorerを使用して、アプリケーションで再配置される DLL を確認することをお勧めします。「View」/「Lower Pain View」メニューでオプション「DLLs」を選択し、「Options」メニューの「Configure Highlighting」で「Relocation DLLs」チェックボックスを選択する必要があります。さらに、すべての DLL に関するどの情報を表示するかをカスタマイズできます。以下のような情報が多いほど、プログラムのロードが遅くなり、アプリケーションのインスタンス間または同じ DLL を使用する異なるアプリケーション間でアドレス空間が共有されなくなります。
上記の例では、ツリー Lenovo DLLTPOSDSVC.dll
とが同じベース アドレスにリンクされており、HKVOLKEY.dll
1つの DLL (ここでは) のみがそのアドレスにロードされます。他の 2 つの DLL を再配置する必要があります。TPLHMM.dll
0x10000000
TPOSDSVC.dll
このテーマについてここで本を書くことはできません。移転の問題についてアプリケーションを検討することをお勧めします。リンカーオプションを使用できます(--image-base
または--enable-auto-image-base
必要なものと思われます)。dumpbin.exeツール (無料版の Visual Studio から) を使用して、PE イメージを調べることができます。
すべての DLL が一意のベース アドレスを持つようになったら、別のツールbind.exe
をオプション付きで使用-u
して、EXE と DLL を依存する DLL にバインドできます。さらに、メモリ サイズが削減され、アプリケーションの起動時間が改善されます。DLL と EXE の一部が更新されIMAGE_DIRECTORY_ENTRY_IMPORT
ます(回答を参照してください)。内部で APIを使用します。多くの Windows インストーラー セットアップでは、BindImageアクションとBindImageテーブルを使用して、EXE と DLL のインストールの最後にバインディングを作成します。IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT
Bind.exe
BindImageEx
DLL と EXE のサイズを小さくするために、他の手法 (ここを参照) を検討できます。
MinGW で遅延ロード手法をどのように使用できるかは正確にはわかりませんが、確実に可能であるはずです。Visual Studio では、2 つの手順を実行する必要があります。Delayimp.lib
追加のライブラリとしてインクルードし、/DELAYLOAD
オプション (こちらを参照) を使用して、直接ではなく最初の使用時にどの DLL をロードするかを指定します。非常に役立つ Tool Dependency Walkerを使用すると、ほとんどの標準 Microsoft DLL がこの手法を使用していることがわかります。この手法も使用すると、アプリケーションの起動時間を改善し、使用メモリを減らすことができます。