DLL入口函數DllMain

來源:互聯網
上載者:User

 BOOL APIENTRY DllMain( HANDLE hModule, DWORD  ul_reason_for_call, LPVOID lpReserved)

  1. DllMain簡介
        跟exe有個main或者WinMain入口函數一樣,DLL也有一個入口函數,就是DllMain。以“DllMain”為關鍵字,來看看MSDN協助文檔怎麼介紹這個函數的:The DllMain function is an optional method of entry into a dynamic-link library (DLL)。(翻譯:DllMain函數是DLL檔案的入口函數,它是可選的。)這句話很重要,很多初學者可能都認為一個動態連結程式庫肯定要有DllMain函數。其實不然,像很多僅僅包含資源資訊的DLL是沒有DllMain函數的。
  2. 何時調用DllMain
        系統是在什麼時候調用DllMain函數的呢?靜態連結或動態連結時調用LoadLibrary和FreeLibrary都會調用DllMain函數。 DllMain的第二個參數fdwReason指明了系統調用Dll的原因,它可能是DLL_PROCESS_ATTACH、 DLL_PROCESS_DETACH、DLL_THREAD_ATTACH和DLL_THREAD_DETACH。
  3. 以下從這四種情況來分析系統何時調用了DllMain。
    (1) DLL_PROCESS_ATTACH
        大家都知道,一個程式要調用Dll裡的函數,首先要先把DLL檔案對應到進程的地址空間。要把一個DLL檔案對應到進程的地址空間,有兩種方法:靜態連結和動態連結的LoadLibrary或者LoadLibraryEx。
        當一個DLL檔案被映射到進程的地址空間時,系統調用該DLL的DllMain函數,傳遞的fdwReason參數為 DLL_PROCESS_ATTACH。這種調用只會發生在第一次映射時。如果同一個進程後來為已經映射進來的DLL 再次調用LoadLibrary或者LoadLibraryEx,作業系統只會增加DLL的使用次數,它不會再用DLL_PROCESS_ATTACH調用DLL的DllMain函數。不同進程用LoadLibrary同一個DLL時,每個進程的第一次映射都會用DLL_PROCESS_ATTACH調用 DLL的DllMain函數。
        可參考DllMainTest的DLL_PROCESS_ATTACH_Test函數。
    (2) DLL_PROCESS_DETACH
        當DLL被從進程的地址空間解除映射時,系統調用了它的DllMain,傳遞的fdwReason
    值是DLL_PROCESS_DETACH。當DLL處理該值時,它應該執行進程相關的清理工作。
        那麼什麼時候DLL被從進程的地址空間解除映射呢?兩種情況:
           ◆FreeLibrary解除DLL映射(有幾個LoadLibrary,就要有幾個FreeLibrary)
           ◆進程結束而解除DLL映射,當然是在進程結束前還沒有這個解除DLL的映射的情況。(如果進程的終結是因為調用了TerminateProcess,系統就不會用 DLL_PROCESS_DETACH來調用DLL的DllMain函數。這就意味著DLL在進程結束前沒有機會執行任何清理工作。)
        注意:當用DLL_PROCESS_ATTACH調用DLL的DllMain函數時,如果返回FALSE,說明沒有初始化成功,系統仍會用DLL_PROCESS_DETACH調用DLL的DllMain函數。因此,必須確保沒有清理那些沒有成功初始化的東西。
        可參考DllMainTest的DLL_PROCESS_DETACH_Test函數。
    (3) DLL_THREAD_ATTACH
        當進程建立一線程時,系統查看當前映射到進程地址空間中的所有DLL檔案映像,並用值DLL_THREAD_ATTACH調用DLL的DllMain函數。
        新建立的線程負責執行這次的DLL的DllMain函數,只有當所有的DLL都處理完這一通知後,系統才允許線程開始執行它的線程函數。
        注意跟DLL_PROCESS_ATTACH的區別,我們在前面說過,第n(n>=2)次以後地把DLL映像檔案對應到進程的地址空間時,是不再用 DLL_PROCESS_ATTACH調用DllMain的。而DLL_THREAD_ATTACH不同,進程中的每次建立線程,都會用值 DLL_THREAD_ATTACH調用DllMain函數,哪怕是線程中建立線程也一樣。
    (4) DLL_THREAD_DETACH
        如果線程調用了ExitThread來結束線程(線程函數返回時,系統也會自動調用ExitThread),系統查看當前映射到進程空間中的所有DLL檔案映像,並用DLL_THREAD_DETACH來調用DllMain函數,通知所有的DLL去執行線程級的清理工作。
        注意:如果線程的結束是因為系統中的一個線程調用了TerminateThread,系統就不會用值DLL_THREAD_DETACH來調用所有DLL的DllMain函數。

 

一個簡單但是介紹很全面的常式 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.