2012-06-04 9 views
5

私はロードに5〜10秒かかるDLLを持っています。つまり、DLLを使用する実行可能ファイルをコンパイルして実行するたびにその時間を待たなければなりません。対応する実行ファイルをコンパイルするたびにすぐにアクセスできるように、DLLをメモリにロードしたままにする方法はありますか? QT MinGWでプログラムをコンパイルしています(該当する場合)。プロセス終了を呼び出した後にDLLをメモリに保持することはできますか?

EDIT:これまでの運がありません。 DLLを別のプログラムにロードすることは効果がないようです(元のプログラムはまだDLLをロードしますが、それと同じくらい時間がかかります)。私は別のプログラムにロードされている場合、DLLとその機能を別々にロードする必要があると思いますが、これを行う方法はわかりません。今はLoadLibraryとGetProcAddressを使用しています。

+3

おそらくメモリに読み込まれているのではなく、DLL内の初期化ロジックがかなり時間がかかります。 DLLをメモリに保持しても、初期化の遅延は回避されません。 –

+0

それは本当なら残念です。私はソースコードにアクセスすることができないと私は何もできないと思いますか? – SharpHawk

+0

アウトオブプロセスのRPCサーバーにラップすることはできますが、これを使用すると、非効率的な高速再接続が行われます。 –

答えて

1

最も簡単な解決策は、DLLの遅延ロードを作るために(MSVC++を仮定した場合)です。もちろん、初期化はまだ行われていなければなりませんが、これでプログラムの他の部分が遅れることはなくなります。例えば。あなたはバックグラウンドスレッドでそれを行うことができます。

+0

私はDLLをメモリに残すことができず、totowtwoの解決策は値段の安いラップトップをさらに遅くすることを意味していたということを考えると、DLLを並列スレッドにロードすることは行く道。私がここでStackOverflowで尋ねた関連する質問でも同じ解決策が提示されました。 – SharpHawk

1

DLLをロードしたままにする明示的にインストールされたシステムサービスを作成します。そのように初期化はブート時に起こり、決して再び起こりません。私は、これらの他の答えの大部分で概説されている方法に対してはお勧めします。彼らは仕事をしているように見えますが、ソフトウェアの悪い行為が気に入っています。ユーザと管理者の両方の視点から、私は明示的にインストールされたシステムサービスをwinlogin.exeにフックする方が好きです。より正直なところ、Windows APIと環境を使用するほど、バージョンやバージョンアップの際にはそれほど大きな変更はありません。私は間違っていないよ場合

+0

それは確かにそのように見えるので、私は私の "いいえ"を編集しました。私はそれらの解決策について不安を感じる。 – totowtwo

+0

初期化は、DLLに接続するすべてのプロセスおよびスレッドに対して行われます。 DLLをサービスにロードしたままにすると、ファイルI/Oだけが保存されます。 –

+0

あなたはこれを行う方法についてもっと詳しく調べることができますか?あなたの答えは、提供されている他の提案の批判です。 – SharpHawk

1

、Windowsはので、この生きているが、動作するはず保つメモリ内のDLLの1つのインスタンスを保持します:

#include <conio.h> 
#include <windows.h> 

int main() 
    { 
    HMODULE handle=LoadLibrary("yourdll.dll"); 
// Make shure Windows resolves the DLL 
    FARPROC dummy=GetProcAddress(handle,"functionInDll"); 
// The process will now just wait for keyboard input. 
    getch(); 
    CloseHandle(handle); 
    return 0; 
    } 
+0

なぜFARPROCを行うかdummy = GetProcAddress(handle、 "functionInDll"); DLLをロードしたままにしておきたい場合は? – rkosegi

+0

Mhm、私のプログラムのインスタンスを開いたままにしました(DLLがロードされています)が、プログラムの新しいインスタンスはDLLをロードするのに同じ時間がかかりました。関数自体を使用することは常に瞬間的です。問題が何であるのだろう... – SharpHawk

2

私は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に関する情報をカスタマイズすることもできます。で

    enter image description here

    :あなたはもっと遅いプログラムがロードされ、より多くのアドレス空間は、アプリケーションのインスタンス間、または同じDLLを使用する異なるアプリケーション間で共有されないことになるでしょう下回っなどのようなより多くの情報上記の例では、ツリーLenovo DLL TPOSDSVC.dllHKVOLKEY.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_IMPORTIMAGE_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がこの手法を使用していることがわかります。このテクニックを使用する場合は、アプリケーションの開始時間を改善し、使用メモリを減らすこともできます。