2010-05-17 70 views
16

我有一個簡單的小問題,誰知道誰會很容易回答,我搜索谷歌,但無法找到答案。.dll文件是爲每個程序加載一次還是爲所有程序加載一次?

有一臺計算機上運行多程序同時,我的問題是:當一個程序加載DLL,它實際上加載DLL文件或者它在其中找到該DLL已經加載內存?例如,爲每個使用winsock的程序加載ws2_32.dll(winsock 2),還是加載一次,並且所有使用它的程序都使用相同的內存地址來調用函數?

回答

18

它的滿載一次,所有程序共享同一代碼在內存中的副本。它有點複雜,但對於DLL的只讀部分(即代碼),操作系統加載程序使用稱爲「內存映射」的技術將DLL映射到進程的地址空間。儘管頁面可能會將頁面映射到其虛擬地址空間中的不同地址,但頁面只會加載到所有進程的物理內存中一次。

但是,每個進程都有一個單獨的數據部分(使全局變量不是共享的 - 除非你明確地請他們),他們顯然也有一個單獨的堆,以便動態分配的內存不共享。

+0

好的,謝謝,這是有道理的。我只需要知道從DLL指向函數的指針是否指向所有使用此函數的程序使用的地址。 – Nilbert 2010-05-17 02:22:20

+2

該問題的答案是「否」。函數指針是進程*虛擬地址空間*中的地址,並且在進程之間絕對不共享。 DLL可以在不同進程的不同地址加載,因此,即使使用相同的物理頁面,函數指針的地址也會不同。 – 2010-05-17 02:25:34

+0

實際上,函數在兩個不同的程序中具有相同的地址是極不可能的。在其之前的所有代碼段貢獻之後,DLL的代碼將被映射到下一個可用地址空間。在Secure Linux中,使用加載地址隨機化(以防止viri在攻擊中使用硬編碼地址)。你沒有寫病毒,是嗎? :-) – wallyk 2010-05-17 02:30:40

5

這取決於你的意思是「裝」什麼。

DLL將共享使用的代碼和數據來製備:最Windows環境兌現可共享(由碼的同一存儲器拷貝映射到每個進程的內存空間)以節省存儲器。但是,從進程的角度來看,「加載」操作的一部分正在運行DLL的初始化:這是在每個進程中分別完成的,每個進程都有不同的數據區副本。

相關問題