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

無我

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

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

本文不是描述怎樣編寫dll程序,也不是說明dll在windows系統(tǒng)的意義。我們的目的是確認(rèn)dll加載到進(jìn)程空間的一些模糊的概念。
本文只能說是我結(jié)合文檔和一些實(shí)驗(yàn)得出的一點(diǎn)猜測(cè)性質(zhì)的結(jié)論,有些結(jié)論并沒有官方Microsoft明確的說明,不保證完全正確,歡迎大家交流,共同學(xué)習(xí)。
 
一、程序加載dll的兩種情況:
比如對(duì)于user32.dll,我們?cè)诔绦蛑邪祟^文件<windows.h>:
1.如果沒有調(diào)用任何user32.dll的函數(shù),那么user32.dll就不會(huì)自動(dòng)加載,可以通過LoadLibrary來手動(dòng)加載。比如如下代碼:
#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;
}

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

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

 總結(jié)一下:dll模塊可能因?yàn)閑xe的輸入函數(shù)而自動(dòng)加載,也可以在運(yùn)行后手動(dòng)加載。

 

二、從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 );
這個(gè)函數(shù)的作用是把可執(zhí)行模塊(exe,dll)映射到調(diào)用進(jìn)程的內(nèi)存空間,同時(shí)增加該dll模塊的引用計(jì)數(shù)(引用計(jì)數(shù)話題后面再討論)。如果是重復(fù)調(diào)用LoadLibrary,則就是增加dll模塊的引用計(jì)數(shù),并返回模塊句柄。

請(qǐng)?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得到的模塊句柄不是全局的,也不是可繼承的。這只在本進(jìn)程中有效!如果其他進(jìn)程希望利用模塊句柄來得到函數(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 );
利用這個(gè)函數(shù)可以得到指定模塊的句柄。注意條件:模塊文件已經(jīng)被映射到了進(jìn)程的地址空間!

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)用進(jìn)程的句柄。也就是本exe程序的基地址,默認(rèn)情況下,是400000h。
 
請(qǐng)注意下面這段話:

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

返回的句柄不是全局的或可繼承的,不能復(fù)制和跨進(jìn)程使用!

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ù)返回模塊句柄,但是不增加引用計(jì)數(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)境下要小心使用得到的句柄,因?yàn)楸灸K在別的線程中釋放了,而有重新加載了別的模塊,并且恰恰復(fù)用了這個(gè)句柄值。這導(dǎo)致利用這個(gè)句柄值訪問的不是期望的模塊。

 

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的引用計(jì)數(shù)。當(dāng)引用計(jì)數(shù)被減到0時(shí),這個(gè)模塊就會(huì)被從進(jìn)程地址空間卸載,并且句柄不再有效。

 
請(qǐng)注意下面這段話:

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.

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

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不會(huì)影響使用相同庫模塊的其他進(jìn)程。

 

總結(jié):

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

1、模塊的句柄HModule不是全局的,也不是可繼承的。也就是說,只是保證對(duì)一個(gè)進(jìn)程唯一的!不能在進(jìn)程間復(fù)制和跨進(jìn)程使用。

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

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

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

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

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

 

對(duì)應(yīng)疑惑:

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

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

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

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

 

 

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

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

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

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

下面是輸出:

我們發(fā)現(xiàn)起初進(jìn)程地址空間中沒有user32.dll。然后通過調(diào)用LoadLibrary,user32.dll被成功的加載。然后通過調(diào)用FreeLibrary,我們也將user32.dll卸載了。這符合我們?cè)诘诙糠值挠懻摗?/p>

不過一個(gè)有趣的現(xiàn)象是:我們?cè)诔绦蛑忻髅髦徽{(diào)用LoadLibrary一次,但是要調(diào)用4次FreeLibrary,才能釋放該模塊!這實(shí)在是有意思。。。

 

我們?cè)賮硌芯康诙N情況,代碼很簡(jiǎn)單,就是把上面的代碼36行的MessageBox一句的注釋去掉。這是的運(yùn)行結(jié)果就有意思了:

之所以沒有后面的,是因?yàn)槌绦蚓陀肋h(yuǎn)的陷入了while循環(huán),永無出頭之日了!也就是無論你怎么調(diào)用FreeLibrary,都無法將該模塊從地址空間卸載!

 

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

正因?yàn)檫@個(gè)特殊情況,也就是我專門寫本文第一部分的原因。希望這樣的編排不影響你的思考。

 

m.shnenglu.com/Tim

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

評(píng)論

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

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

這個(gè)結(jié)論不對(duì)的

user32.dll kernel32.dll ntdll.dll等不能卸載是其它機(jī)制原因
鏈接的是自己的或者非常駐dll可以卸載的
  回復(fù)  更多評(píng)論   

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

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

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

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

注:vs2005,win8  回復(fù)  更多評(píng)論   

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

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

<2009年3月>
22232425262728
1234567
891011121314
15161718192021
22232425262728
2930311234

導(dǎo)航

統(tǒng)計(jì)

公告

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

留言簿(9)

隨筆分類(173)

IT

Life

搜索

積分與排名

最新隨筆

最新評(píng)論

閱讀排行榜

青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <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>
            一本在线高清不卡dvd| 免费在线亚洲欧美| 欧美一级在线视频| 欧美在线视频免费观看| 亚洲麻豆av| 亚洲视频图片小说| 猫咪成人在线观看| 欧美高清在线一区二区| 欧美激情成人在线| 亚洲精品一区二区三区四区高清 | 国产精品一区二区久久国产| 久久男女视频| 亚洲高清三级视频| 欧美亚洲视频在线看网址| 99riav1国产精品视频| 亚洲国产精品一区二区www| 韩日欧美一区二区| 红杏aⅴ成人免费视频| 亚洲啪啪91| 夜夜精品视频一区二区| 亚洲乱码国产乱码精品精 | 国产毛片精品国产一区二区三区| 欧美日韩专区在线| 国产欧美一区二区精品婷婷| 亚洲国产日韩欧美在线动漫| 亚洲欧美激情视频| 亚洲福利视频网| 亚洲午夜高清视频| 久久精品视频免费播放| 欧美日韩精品高清| 黑人中文字幕一区二区三区| 一区二区三区高清在线观看| 老司机成人在线视频| 一区二区三区高清在线| 久久本道综合色狠狠五月| 欧美成人综合在线| 黄色成人免费网站| 香蕉国产精品偷在线观看不卡 | 欧美专区福利在线| 亚洲国产精品成人综合色在线婷婷| 国产精品99久久久久久人| 免费观看日韩| 国产亚洲综合性久久久影院| 99视频精品全国免费| 你懂的亚洲视频| 欧美大片在线看免费观看| 国产亚洲一本大道中文在线| 亚洲视频在线观看网站| 亚洲国产精品成人va在线观看| 久久精品理论片| 欧美在线视频网站| 国产专区精品视频| 欧美影院精品一区| 制服诱惑一区二区| 欧美美女福利视频| 日韩午夜激情电影| 亚洲激情中文1区| 欧美99久久| 狠狠色综合播放一区二区| 午夜欧美精品| 亚洲一区二区三区免费观看| 久久亚洲精品一区二区| 久久久久久久久一区二区| 亚洲最新视频在线播放| 欧美金8天国| 亚洲精品美女在线| 亚洲国产一区二区三区a毛片| 久久亚洲精品一区二区| 在线免费高清一区二区三区| 久久久噜噜噜久久中文字免| 欧美淫片网站| **欧美日韩vr在线| 欧美高清视频免费观看| 欧美α欧美αv大片| 亚洲免费电影在线| 日韩视频欧美视频| 国产精品视频99| 久久久久国内| 久久综合久久综合久久| 99国产成+人+综合+亚洲欧美| 亚洲精品少妇| 欧美色另类天堂2015| 黄色日韩网站| 亚洲第一色在线| 欧美性猛交xxxx乱大交退制版 | 欧美日韩精品高清| 亚洲综合日本| 亚洲成色777777女色窝| 亚洲精品偷拍| 国产一区二区黄色| 亚洲成色www久久网站| 欧美午夜电影网| 久久久国产精品亚洲一区| 猫咪成人在线观看| 亚洲欧美国产制服动漫| 久久最新视频| 亚洲欧美在线视频观看| 久久全国免费视频| 亚洲综合色丁香婷婷六月图片| 亚洲欧美日韩国产中文 | 国产一区二区三区在线播放免费观看| 欧美激情视频在线播放| 国产欧美精品在线观看| 欧美激情一区二区三区| 国产精品久久久久高潮| 欧美激情在线有限公司| 国产日韩av一区二区| 亚洲国产欧美一区| 国产一在线精品一区在线观看| 欧美激情麻豆| 国产精品亚洲精品| 亚洲精品1区| 欧美午夜一区二区福利视频| 免费一级欧美片在线播放| 国产精品一区一区| 亚洲精品国产系列| 在线观看日韩av电影| 亚洲女同性videos| 亚洲精品社区| 国产亚洲a∨片在线观看| 欧美激情精品久久久六区热门| 国产精品久久久久9999| 亚洲福利小视频| 在线不卡视频| 欧美伊人久久久久久久久影院| 亚洲一区二区四区| 欧美日韩黄色大片| 欧美激情2020午夜免费观看| 国产精品中文在线| 一区二区激情视频| 一区二区毛片| 女仆av观看一区| 欧美国产免费| 亚洲激情综合| 欧美激情免费观看| 亚洲精品午夜精品| 一本久道综合久久精品| 欧美电影在线| 另类天堂视频在线观看| 狠狠色丁香久久婷婷综合丁香 | 亚洲私人影院在线观看| 夜夜夜精品看看| 亚洲欧洲99久久| 香蕉久久国产| 国产精品人人做人人爽| 亚洲午夜国产成人av电影男同| 亚洲网站视频| 国产精品福利在线观看网址| 亚洲视频综合| 久久久99国产精品免费| 国产自产精品| 久久福利影视| 欧美成人午夜| 日韩午夜在线电影| 欧美日韩国产欧| 亚洲私人黄色宅男| 欧美专区在线播放| 国产精品伊人日日| 久久精品国产综合精品| 欧美成人在线影院| 99这里只有精品| 国产精品乱码妇女bbbb| 性18欧美另类| 亚洲国产小视频| 午夜精品久久久久久久白皮肤| 国产午夜亚洲精品不卡| 欧美成人午夜激情| 在线视频精品| 久久久美女艺术照精彩视频福利播放| 一区在线播放| 欧美黄色小视频| 亚洲图片在区色| 久久蜜桃精品| 日韩视频在线观看国产| 国产精品视频一二三| 午夜精品一区二区三区在线| 免费高清在线视频一区·| aa亚洲婷婷| 亚洲精品欧美日韩专区| 欧美一区二区黄| 欧美激情第4页| 香港成人在线视频| 亚洲精品视频在线播放| 国产精品国产成人国产三级| 久久久久久高潮国产精品视| 99视频一区| 亚洲大胆av| 久久久91精品| 午夜精品福利在线| 久久精品视频网| 亚洲精品社区| 激情六月婷婷久久| 国产精品久久久99| 欧美精品久久久久久久免费观看 | 久久久欧美精品| 在线亚洲激情| 欧美成人综合网站| 午夜久久福利| 亚洲电影观看| 国产字幕视频一区二区|