1. 程式人生 > >多個程序間共享動態連結庫的原理

多個程序間共享動態連結庫的原理

同樣這個問題是我在面試總監的時候,總監問我的一個問題,這些天一直 忙活,都沒有好好看書了,今天總結一下這個問題?為什麼一個程序用完一個動態連結庫以後另一個程序還可以繼續使用呢?當時回答的很是籠統,只說對了答案的一半,現在就在這裡好好總結一下吧!
前面我們已經說過程序間的通訊有好幾種方式,其實現在我們講的這種動態連結庫也是程序間的通訊方式之一。
不管是windows還是Linux作業系統其實所有的作業系統的內涵知識都是一樣的。
動態連結庫是windows作業系統的基礎,其中windows API基本上都是以動態連結庫的形式來提供的,通常來說動態連結庫是不能夠直接執行,也不能直接接收訊息的,他們是一些獨立的檔案(字尾名一般為.dll,當然還有其它的一些字尾名也是可以的),其中包含能被可執行程式或其它DLL呼叫來完成某項工作的函式,也就是說動態連結庫也就是由一些函式組成而已。並且只有在其它模組呼叫動態連結庫中的函式時,動態連結庫才發揮作用,在實際的程式設計中,通常可以完成某種功能的函式放在一個動態連結庫中,然後提供給其它函式呼叫。當這個訪問了的動態連結庫的程序被載入時,系統會為這個程序分配4GB的私有地址空間(如果是32位機的話),然後系統就會分析這個可執行模組,找到這個可執行模組中將所要呼叫的DLL,然後系統就負責搜尋這些DLL找到這些DLL後便將這些DLL載入到記憶體中,併為他們分配虛擬記憶體空間,最後將DLL的頁面對映到呼叫程序的地址空間彙總,DLL的虛擬記憶體有內碼表和資料頁,他們被分別對映到程序A的程式碼頁面和資料頁面,如果這時程序B也啟動了,並且程序B也許要訪問該DLL,這時,只需要將該DLL在虛擬記憶體中的程式碼頁面和資料頁面對映到第二個程序的地址空間即可。這也表明了在記憶體中,只需要存在一份DLL的程式碼和資料。

多個程序共享DLL

的同一份程式碼,很明顯這樣做可以節省記憶體空間的。

但是在Windows下(Linux中也是一樣的),由於系統會為每一個程序分配4GB的私有地址空間,

DLL中的程式碼和資料也只是對映到了這個私有地址空間中,所以這些應用程式之間還是不能夠相互影響的,

也就是說多個應用程式雖然是可以共享同一個DLL中的相同的程式碼的,

但是DLL為每一個程序儲存的資料都是不相同的,

並且每一個程序都為DLL使用的全部資料分配了自己的地址空間,

舉個最簡單的例子,我的DLL中有一個函式為int  Add(int    num1 ,   int    num2)

這個函式的作用是實現num1 num2

相加並返回相加後的結果。

然後我有一個程序 A  使用了這個DLL,並且其呼叫了函式 Add(10, 20),

然後我還有一個程序 B其也使用了這個DLL,並且其呼叫了函式Add(30, 40),

那麼對於程序 A中的資料1020其實是儲存在程序 A的私有地址空間中的,

而對於程序 B中的資料3040則是儲存在程序 B的私有地址空間中的,

上面這個簡單的例子表明如果單單用這種簡單的使用動態連結庫的方式是不能夠實現程序之間的通訊的。

如果想利用動態連結庫來實現程序間的通訊的話,那麼有一種方案可以試一試,

即從系統為動態連結庫分配的那一塊記憶體(系統需要將動態連結庫載入到記憶體中)下手,

由於在記憶體中,動態連結庫其實只存在一份,

其被所有需要呼叫該動態連結庫中的函式的模組或者簡單說是可執行程式所共享,

既然是共享的話,如果我在系統給動態連結庫分配的這塊記憶體中儲存資料,

那豈不是可以被所有訪問該動態連結庫的可執行程式所獲取或者說設定。

這樣的話,我就可以使用程序 A來設定好這個共享記憶體中的資料,

然後程序 B就可以讀取這個共享記憶體中的資料了,這不是也可以實現程序間的通訊嘛,

這樣看來的話,其思路其實和使用剪貼簿是一模一樣的了。

也是採用一塊兩個程序共享的記憶體來作為存放資料的中介。