私はMinGW開発者ではありませんが、あなたの質問は非常に一般的で、実際にDLLを作成する方法に依存しません。 DLL遅延ローディングの(アプリケーションのインストール時)DLLとEXEを結合
のDLLの固有のベースアドレスの
- 選ん
- が使用:このような問題は、典型的には、3つの技術の使用により解決することによって意志技術
- 少しロード時間を
DllMain
正確SのDLL_PROCESS_ATTACH
一部の内部DisableThreadLibraryCallsの呼び出しを改善しますあなたが使用できるリンカや他のツールの魔法使いはあなたの開発環境に依存します。
実行可能ファイルまたはDLLがどのようにロードされるかを知っておく必要があります。まず、EXEまたはDLLがメモリにマップされます。 EXE/DLLを指すMemory mapped file(セクション)が作成されます。したがって、アクセスにはEXE/DLLファイルに対応するプロセスのいくつかのアドレスがあります。 DLLをリンクする場合は、ベースアドレスを選択することができます。アドレスがプロセス・アドレス空間で使用されていない場合、何も行われません。最初の行のコードが使用される(DLLからいくつかの関数を呼び出す)場合、使用されたアドレスの近くのメモリ8Kのページは、ファイルからメモリにロードされます。 2つのプロセスが同じDLLを使用する場合、コードの物理メモリはプロセス間で共有になります。初期化された変数を保持していても、変数を含むページは変数の最初の変更まで共有されます。変更を行ったプロセスのメモリページのコピーが変更されます。
DLLがプロセスにロードされた後、呼び出し元の一部(たとえばEXE)をDLLから使用される関数の実際のアドレスを含むように変更する必要があります。同じことが、別の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 DLL TPOSDSVC.dll
、HKVOLKEY.dll
およびTPLHMM.dll
は同じベースアドレス0x10000000
にリンクされており、アドレスには1つのDLL(TPOSDSVC.dll
)がロードされます。 2つの他の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
とIMAGE_DIRECTORY_ENTRY_DELAY_IMPORT
部分が更新されます(the answer参照)。 Bind.exe
は内部でBindImageEx
APIを使用します。多くのWindowsインストーラのセットアップでは、BindImageアクションとBindImageテーブルを使用して、EXEとDLLのインストールの最後にバインディングを作成します。
DLLとEXEのサイズを減らすために、他の手法(hereを参照)を検討することができます。
私はMinGWで遅延ロード手法をどのように使用できるかについては正確にはわかりませんが、確実に可能なはずです。 Visual Studioでは、2つの手順を実行する必要があります。追加ライブラリとしてDelayimp.lib
を追加し、オプション(here参照)を使用して、最初の使用時にロードするDLLを直接ではなく指定します。非常に有用なツールDependency Walkerを使用すると、ほとんどの標準Microsoft DLLがこの手法を使用していることがわかります。このテクニックを使用する場合は、アプリケーションの開始時間を改善し、使用メモリを減らすこともできます。
おそらくメモリに読み込まれているのではなく、DLL内の初期化ロジックがかなり時間がかかります。 DLLをメモリに保持しても、初期化の遅延は回避されません。 –
それは本当なら残念です。私はソースコードにアクセスすることができないと私は何もできないと思いますか? – SharpHawk
アウトオブプロセスのRPCサーバーにラップすることはできますが、これを使用すると、非効率的な高速再接続が行われます。 –