青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

無我

讓內(nèi)心永遠燃燒著偉大的光明的精神之火!
靈活的思考,嚴謹?shù)膶崿F(xiàn)
豪邁的氣魄、頑強的意志和周全的思考

關(guān)于dll加載的一些理解

本文不是描述怎樣編寫dll程序,也不是說明dll在windows系統(tǒng)的意義。我們的目的是確認dll加載到進程空間的一些模糊的概念。
本文只能說是我結(jié)合文檔和一些實驗得出的一點猜測性質(zhì)的結(jié)論,有些結(jié)論并沒有官方Microsoft明確的說明,不保證完全正確,歡迎大家交流,共同學習。
 
一、程序加載dll的兩種情況:
比如對于user32.dll,我們在程序中包含了頭文件<windows.h>:
1.如果沒有調(diào)用任何user32.dll的函數(shù),那么user32.dll就不會自動加載,可以通過LoadLibrary來手動加載。比如如下代碼:
#include "stdafx.h"
#include 
<Windows.h>
int _tmain(int argc, _TCHAR* argv[])
{
    
//HINSTANCE hInstance1 = LoadLibrary("user32.dll");
    HMODULE hModule1 = GetModuleHandle("user32.dll");
    
if (!hModule1)
    
{
        printf(
"Not auto load user32.dll!\n");
    }

    
else
    
{
        printf(
"OK,auto load user32.dll!\n");
    }

    
//MessageBox(0,"System will auto load user32.dll because of the MessageBox function","tim",0);
    getchar();
    
return 0;
}

運行結(jié)果告訴我們user32.dll沒有被加載,而且exe程序的輸入表中也沒有user32.dll:

 2.如果我們在程序中調(diào)用了dll中的函數(shù),比如MessageBox,那么編譯器會自動將user32.dll中的MessageBoxA(W)寫到輸入表中,這樣user32.dll就會在進程啟動時自動加載到地址空間。代碼就是上面的,只是把MessageBox一句的注釋去掉。其運行結(jié)果和輸入表如下:

 總結(jié)一下:dll模塊可能因為exe的輸入函數(shù)而自動加載,也可以在運行后手動加載。

 

二、從MSDN文檔來研究操作dll的API

1、LoadLibrary

The LoadLibrary function maps the specified executable module into the address space of the calling process.

For additional load options, use the LoadLibraryEx function.

HMODULE LoadLibrary(  LPCTSTR lpFileName );
這個函數(shù)的作用是把可執(zhí)行模塊(exe,dll)映射到調(diào)用進程的內(nèi)存空間,同時增加該dll模塊的引用計數(shù)(引用計數(shù)話題后面再討論)。如果是重復調(diào)用LoadLibrary,則就是增加dll模塊的引用計數(shù),并返回模塊句柄。

請?zhí)貏e注意下面這段話:

Module handles are not global or inheritable. A call to LoadLibrary by one process does not produce a handle that another process can use — for example, in calling GetProcAddress. The other process must make its own call to LoadLibrary for the module before calling GetProcAddress.

利用LoadLibrary得到的模塊句柄不是全局的,也不是可繼承的。這只在本進程中有效!如果其他進程希望利用模塊句柄來得到函數(shù)地址,必須自己調(diào)用LoadLibrary來獲取句柄!

 

2、GetModuleHandle

The GetModuleHandle function retrieves a module handle for the specified module if the file has been mapped into the address space of the calling process.

To avoid the race conditions described in the Remarks section, use the GetModuleHandleEx function. 

HMODULE GetModuleHandle(  LPCTSTR lpModuleName );
利用這個函數(shù)可以得到指定模塊的句柄。注意條件:模塊文件已經(jīng)被映射到了進程的地址空間!

If this parameter is NULL, GetModuleHandle returns a handle to the file used to create the calling process (.exe file).

如果參數(shù)為NULL,那么本函數(shù)就返回調(diào)用進程的句柄。也就是本exe程序的基地址,默認情況下,是400000h。
 
請注意下面這段話:

The returned handle is not global or inheritable. It cannot be duplicated or used by another process.

返回的句柄不是全局的或可繼承的,不能復制和跨進程使用!

If lpModuleName does not include a path and there is more than one loaded module with the same base name and extension, you cannot predict which module handle will be returned. To work around this problem, you could specify a path, use side-by-side assemblies, or use GetModuleHandleEx to specify a memory location rather than a DLL name.

The GetModuleHandle function returns a handle to a mapped module without incrementing its reference count. Therefore, use care when passing the handle to the FreeLibrary function, because doing so can cause a DLL module to be unmapped prematurely.

本函數(shù)返回模塊句柄,但是不增加引用計數(shù)!

This function must be used carefully in a multithreaded application. There is no guarantee that the module handle remains valid between the time this function returns the handle and the time it is used. For example, a thread retrieves a module handle, but before it uses the handle, a second thread frees the module. If the system loads another module, it could reuse the module handle that was recently freed. Therefore, first thread would have a handle to a module different than the one intended.

多線程環(huán)境下要小心使用得到的句柄,因為本模塊在別的線程中釋放了,而有重新加載了別的模塊,并且恰恰復用了這個句柄值。這導致利用這個句柄值訪問的不是期望的模塊。

 

3、FreeLibrary

The FreeLibrary function decrements the reference count of the loaded dynamic-link library (DLL). When the reference count reaches zero, the module is unmapped from the address space of the calling process and the handle is no longer valid.

BOOL FreeLibrary( HMODULE hModule ); 本函數(shù)減少加載的dll的引用計數(shù)。當引用計數(shù)被減到0時,這個模塊就會被從進程地址空間卸載,并且句柄不再有效。

 
請注意下面這段話:

Each process maintains a reference count for each loaded library module. This reference count is incremented each time LoadLibrary is called and is decremented each time FreeLibrary is called. A DLL module loaded at process initialization due to load-time dynamic linking has a reference count of one. This count is incremented if the same module is loaded by a call to LoadLibrary.

每一個進程管理自己的每一個模塊的引用計數(shù)。引用計數(shù)在每次調(diào)用LoadLibrary時遞增,在調(diào)用FreeLibrary時遞減。

Before unmapping a library module, the system enables the DLL to detach from the process by calling the DLL's DllMain function, if it has one, with the DLL_PROCESS_DETACH value. Doing so gives the DLL an opportunity to clean up resources allocated on behalf of the current process. After the entry-point function returns, the library module is removed from the address space of the current process.

It is not safe to call FreeLibrary from DllMain. For more information, see the Remarks section in DllMain.

Calling FreeLibrary does not affect other processes using the same library module.

調(diào)用FreeLibrary不會影響使用相同庫模塊的其他進程。

 

總結(jié):

通過上面三個函數(shù)的說明,我們發(fā)現(xiàn)可以得到以下一些明確的概念:

1、模塊的句柄HModule不是全局的,也不是可繼承的。也就是說,只是保證對一個進程唯一的!不能在進程間復制和跨進程使用。

這也就是說,在不同的進程中,對同一個模塊(dll等),得到的HMODULE不一定相同。系統(tǒng)并不保證這個值全局唯一。

2、模塊的加載和卸載是由引用計數(shù)來判斷的。LoadLibrary會遞增引用計數(shù),F(xiàn)reeLibrary會遞減引用計數(shù)。當引用計數(shù)減少到0時,才會卸載該模塊在進程空間的映射。(下文還有一個特殊情況要討論)

3、模塊的引用計數(shù)是進程自己管理的!所以一個進程中引用計數(shù)的變化不會影響其他的進程。

請記住模塊的引用計數(shù)是進程自己管理的。你在一個進程中調(diào)用無限次的FreeLibrary也不會影響別的進程正常使用這個庫模塊。

4、如果只是要查看某個模塊是否被映射,而得到其模塊句柄時,請調(diào)用GetModuleHandle。本函數(shù)不會主動加載,也不會變更模塊的引用計數(shù)。

 

對應疑惑:

1、我們經(jīng)常發(fā)現(xiàn),在很多不同的程序中,得到某個指定dll的HMODULE好像都是相同的,所以容易誤以為這個值是全局唯一。但是MSDN告訴我們這是不可靠的,這個判斷是錯誤的。

之所以很多情況下相同時,其實是涉及到PE加載和重定位的問題。對PE的映射,windows盡量將模塊映射到PE指定的地址,來省卻重定位的工作。大部分情況下,那些dll的地址是不沖突的,所以就映射成功,所以不同的程序得到的HMODULE值相同。但是這并不代表任何時候都條件滿足,比如由于程序很大,用到了很多庫,那么就可能導致其默認地址被占用,必須映射到別的地方,那么他的HMODULE就不同。

而且,對應“HMODULE值系統(tǒng)全局唯一”的觀點,很容易就可以得出一個反例:對VS編譯的exe程序,如果沒有指定基地址選項,那么所有不同的進程調(diào)用GetModuleHandle(NULL)得到的都是400000h,很明顯,對不同的模塊,卻有相同的值,所以可見該值不是全局的。

2、模塊的引用計數(shù)是進程自己管理的。也就是你無論怎么調(diào)用LoadLibrary和FreeLibrary,都只會影響本進程的引用計數(shù)。不要誤認為是系統(tǒng)維護的。

 

 

三、關(guān)于引用計數(shù)遞減到0會導致模塊卸載映射的問題

上文提到模塊的引用計數(shù)遞減到0時,就會將模塊從進程的地址空間卸載,有一個特殊情況。這里就來討論這個特殊情況。

第一部分我們說明了dll加載的兩種情況,在這里正是派上用場的地方!

我們先看第一種情況,代碼如下:

下面是輸出:

我們發(fā)現(xiàn)起初進程地址空間中沒有user32.dll。然后通過調(diào)用LoadLibrary,user32.dll被成功的加載。然后通過調(diào)用FreeLibrary,我們也將user32.dll卸載了。這符合我們在第二部分的討論。

不過一個有趣的現(xiàn)象是:我們在程序中明明只調(diào)用LoadLibrary一次,但是要調(diào)用4次FreeLibrary,才能釋放該模塊!這實在是有意思。。。

 

我們再來研究第二種情況,代碼很簡單,就是把上面的代碼36行的MessageBox一句的注釋去掉。這是的運行結(jié)果就有意思了:

之所以沒有后面的,是因為程序就永遠的陷入了while循環(huán),永無出頭之日了!也就是無論你怎么調(diào)用FreeLibrary,都無法將該模塊從地址空間卸載!

 

結(jié)論:對于由輸入表導入的模塊,不管他是否采用引用計數(shù)機制,都無法希望利用FreeLibrary遞減引用計數(shù)而卸載!

正因為這個特殊情況,也就是我專門寫本文第一部分的原因。希望這樣的編排不影響你的思考。

 

m.shnenglu.com/Tim

posted on 2012-05-22 15:27 Tim 閱讀(6176) 評論(4)  編輯 收藏 引用 所屬分類: windows系統(tǒng)

評論

# re: 關(guān)于dll加載的一些理解 2012-05-23 12:51 Lo

結(jié)論:對于由輸入表導入的模塊,不管他是否采用引用計數(shù)機制,都無法希望利用FreeLibrary遞減引用計數(shù)而卸載!

這個結(jié)論不對的

user32.dll kernel32.dll ntdll.dll等不能卸載是其它機制原因
鏈接的是自己的或者非常駐dll可以卸載的
  回復  更多評論   

# re: 關(guān)于dll加載的一些理解 2012-05-23 13:44 Tim

你可以試試上面的代碼。如果user32.dll由輸入表導入的,是無法卸載的。而如果沒有導入,是可以卸載的。這說明user32.dll本來就是可選的,不是常駐的了。不過,是不是“由輸入表導入的模塊”也就成為了你說的常駐dll,那就不知道了。呵呵@Lo
  回復  更多評論   

# re: 關(guān)于dll加載的一些理解 2015-06-23 16:03 akaka

@Tim
我用上面的代碼,注釋掉messagebox代碼,也是沒法跳出while循環(huán)的。
也就是說在我的編譯環(huán)境下即使是自己loadlibary的user32.dll,也是無法卸載的。

注:vs2005,win8  回復  更多評論   

# re: 關(guān)于dll加載的一些理解[未登錄] 2015-07-30 11:12 劉偉

不知道樓主是否研究過為什么要FreeLibrary多次才能卸載掉的問題?很是困惑  回復  更多評論   

<2025年9月>
31123456
78910111213
14151617181920
21222324252627
2829301234
567891011

導航

統(tǒng)計

公告

本博客原創(chuàng)文章,歡迎轉(zhuǎn)載和交流。不過請注明以下信息:
作者:TimWu
郵箱:timfly@yeah.net
來源:m.shnenglu.com/Tim
感謝您對我的支持!

留言簿(9)

隨筆分類(173)

IT

Life

搜索

積分與排名

最新隨筆

最新評論

閱讀排行榜

青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            日韩视频一区二区三区在线播放| 日韩亚洲精品电影| 欧美亚洲尤物久久| 亚洲欧洲一区二区三区在线观看 | 蜜桃av一区二区三区| 久久天堂国产精品| 毛片一区二区三区| 国产精品久久久久久福利一牛影视| 99亚洲一区二区| 99精品免费| 国产亚洲一区二区三区在线播放| 久久久精品999| 国产精品久久一区主播| 久久久99精品免费观看不卡| 欧美一级精品大片| 亚洲精品护士| 欧美高清一区二区| 美女主播视频一区| 日韩视频免费| 亚洲一区二区av电影| 国产精品国产三级国产aⅴ浪潮| 亚洲免费在线看| 怡红院精品视频在线观看极品| 亚洲精品欧美在线| 亚洲国产欧美一区| 91久久精品国产91久久性色tv| 午夜伦理片一区| 欧美色播在线播放| 欧美在线free| 另类av一区二区| 国内精品久久久久影院薰衣草| 一本色道久久综合亚洲91| 在线成人性视频| 国产视频亚洲精品| 亚洲精品美女久久7777777| 欧美一级二级三级蜜桃| 午夜精品久久久久久久99热浪潮| 亚洲国产综合在线看不卡| 红桃视频一区| 欧美成在线观看| 久久女同互慰一区二区三区| 国内精品免费在线观看| 欧美视频不卡| 国产一区二区精品久久91| 国产精品丝袜xxxxxxx| 在线视频欧美精品| 亚洲片国产一区一级在线观看| 久久躁日日躁aaaaxxxx| 午夜综合激情| 久久香蕉国产线看观看网| 久久午夜精品一区二区| 国产日韩欧美综合在线| 日韩亚洲欧美成人| 欧美成人亚洲成人| 欧美特黄一级| 国产欧美精品在线播放| 久久精品国产综合| 欧美精品成人一区二区在线观看| 欧美综合国产| 亚洲国产精品尤物yw在线观看| 亚洲国产欧美在线| 亚洲性夜色噜噜噜7777| 国产精品久久久久久久久婷婷 | 亚洲激情偷拍| 亚洲欧美在线视频观看| 久久精视频免费在线久久完整在线看| 亚洲第一精品福利| 亚洲免费网址| 亚洲精品日韩精品| 久久久久久网| 亚洲午夜激情在线| 亚洲国产欧美国产综合一区| 亚洲制服av| 亚洲蜜桃精久久久久久久| 久久精品国产亚洲5555| 亚洲欧美文学| 欧美中文字幕第一页| 久久网站热最新地址| 欧美在线影院| 欧美午夜精品理论片a级按摩 | 国产一区二区三区日韩| 久久深夜福利免费观看| 亚洲国产精品久久精品怡红院| 午夜精品视频在线观看| 欧美va亚洲va国产综合| 亚洲一区日韩| 欧美激情一区二区三区高清视频 | 午夜综合激情| 亚洲婷婷综合久久一本伊一区| 国产精品成人v| 久久精品日产第一区二区| 欧美另类久久久品| 欧美成人性生活| 亚洲美女网站| 激情偷拍久久| 亚洲国产精品一区二区三区| 老色批av在线精品| 亚洲欧美高清| 国产精品入口尤物| 欧美影视一区| 欧美成人自拍| 午夜精品视频在线观看| 久久久国际精品| 国产精品99久久久久久人 | 亚洲欧美激情视频在线观看一区二区三区| 亚洲黄色高清| 欧美三级电影一区| 亚洲欧美一区二区三区极速播放| 麻豆91精品91久久久的内涵| 午夜精品网站| 欧美国产欧美亚州国产日韩mv天天看完整| 欧美成人三级在线| 欧美乱妇高清无乱码| 午夜亚洲影视| 亚洲福利视频免费观看| 性做久久久久久| 亚洲第一中文字幕| 欧美14一18处毛片| 亚洲人成小说网站色在线| 狂野欧美一区| 黄色日韩网站| 久久久一区二区| 久久成人精品| 国内精品久久久久影院色 | 久久精品国产免费观看| 亚洲一区二区三区四区中文 | 一本色道婷婷久久欧美| 亚洲一区二区三区在线播放| 亚洲黄色在线| 欧美激情一区二区三区| 亚洲精品自在在线观看| 一本久道久久综合中文字幕| 亚洲欧洲在线免费| 男女精品视频| 国产伦精品一区二区三区视频孕妇 | 国产精品久久久久久久久久三级| 亚洲淫性视频| 欧美精品一区二区三区一线天视频| 亚洲国产精品激情在线观看| 国产精品影片在线观看| 久久se精品一区二区| 性伦欧美刺激片在线观看| 欧美欧美天天天天操| 亚洲五月六月| 欧美一区二区三区的| 欧美国产亚洲另类动漫| 亚洲欧美福利一区二区| 亚洲午夜精品17c| 国产精品一区二区在线观看| 国产精品成人av性教育| 国产精品一区二区三区成人| 欧美国产日韩一区| 99精品福利视频| 久久爱www.| 欧美另类久久久品| 亚洲欧美日韩综合国产aⅴ| 欧美88av| 欧美人在线视频| 在线播放中文一区| 免费观看成人www动漫视频| 久久综合999| 久久亚洲欧美国产精品乐播| 亚洲欧洲在线一区| 欧美日韩精品免费观看视频完整| 亚洲天堂av在线免费观看| 日韩香蕉视频| 91久久精品美女高潮| 欧美精品一区二区在线播放| 99精品久久久| 亚洲午夜久久久久久尤物| 亚洲午夜精品福利| 亚洲少妇一区| 好男人免费精品视频| 欧美日韩天堂| 久久av最新网址| 亚洲国产欧美久久| 亚洲精品日本| 在线看一区二区| 国产精品任我爽爆在线播放 | 91久久精品国产| 亚洲特黄一级片| 在线电影院国产精品| 欧美不卡视频| 亚洲人成网站在线播| 亚洲视频一区| 国产真实久久| 可以看av的网站久久看| 亚洲另类一区二区| 欧美一区激情| 久久精彩免费视频| 亚洲国产老妈| 国产精品成人一区| 欧美日韩高清区| 在线综合亚洲| 亚洲在线视频免费观看| 91久久国产综合久久蜜月精品 | 久久国产99| 黄网站免费久久| 国产亚洲福利社区一区| 欧美激情亚洲综合一区|