動態鏈結和靜態鏈結不同,為了節省空間,在鏈結的時候,動態庫只是將自己的符號表與可執行檔案繫結在了一起生成了乙個.o的可執行檔案,真正的鏈結,實際上發生在程式執行實施裝載的時候。
裝載的時候,作業系統將動態鏈結器載入完後(動態鏈結器也是乙個共享物件),就將控制權交給動態鏈結庫器的入口位址。當動態鏈結器得到控制權後,它就開始將自身進行初始化,然後根據當前的環境引數,對可執行檔案進行動態鏈結工作。當所有的動態鏈結工作結束了之後,動態鏈結器會將控制權交給可執行檔案的入口位址,程式真正開始執行。
1. 啟動動態鏈結器本身
2. 裝載所有需要的共享物件
3. 重定位和初始化
由於動態鏈結器本身就是乙個共享物件,那麼它的重定位的工作由誰來完成呢?所以,動態鏈結器必須有它的特殊性:
1. 動態鏈結器本身不可以依賴於其他任何共享物件
2. 動態鏈結器本身所需要的全域性和靜態變數的重定位工作由自身完成
為了達到這些要求,動態鏈結器首先應不使用任何系統庫、執行庫;對於第二個條件,動態鏈結器必須在啟動時有一段**可以完成這項任務同時又不用到任何的全域性和靜態變數。這種具有一定限制條件的啟動**被稱為自舉。
自舉**先找到動態鏈結器本身的「.dynamic」段,通過段中的資訊,自舉**便可以獲得動態鏈結器本身的重定位表和符號表,從而得到動態鏈結器本身的重定位入口,然後進行重定位。
這一步結束後,動態鏈結器才開始可以使用自己的全域性變數和靜態變數。
完成基本的自舉之後,動態鏈結器可執行檔案和鏈結器本身的符號表都合併到乙個符號表當中,稱為 全域性符號表 ,然後鏈結器開始尋找可執行檔案所依賴的共享物件。並將所有共享物件的符號表合併到全域性符號表中。若共享物件還依賴於其他的共享物件,就將其他的共享物件新增進符號表,直到全部完成,(如果將依賴關係看成乙個圖的話,那麼這個裝載過程就是乙個圖的遍歷過程,一般使用廣度優先)
當上面的步驟結束之後,鏈結器開始重新編遍歷可執行檔案和每個共享物件的重定位表,將他們的got(全域性偏移表)/plt(延遲繫結)中的每個需要重定位的位置進行修正(根據全域性符號表)。
重定位完成之後,如果某個共享物件有「.init」段,那麼動態鏈結器執行「.init」段的**,用以實現共享物件特有的初始化過程。
可執行檔案中的「.init」段鏈結器不會去執行,因為這些由程式初始化部分**負責執行。
當完成了重定位和初始化後,所有的準備工作就完成了,所有的共享物件都裝載完成並且鏈結好了。這時候鏈結器就會將控制權轉交給程式的入口開始執行。
2017/04/21 20:27
動態鏈結器(三) 動態鏈結的步驟和實現
大體步驟 動態鏈結器的自舉 與 dynamic 段有關 裝載共享物件 涉及全域性符號表,符號優先順序等 重定位與初始化 1 gcc xlinker rpath 表示鏈結器在當前路徑尋找共享物件 2 當共享庫被裝載到程序的位址空間,則同時它們中的符號都會被併入到全域性符號表 3 完成自舉以後,動態鏈結...
動態鏈結庫 實現
靜態鏈結 平台 windows2000 xp 工具 vc 6.0 建立步驟 1.新建專案 win32 static library 2 選擇pre pliled header 3 編輯標頭檔案和實現檔案 4 編譯 生成 lib檔案 參考 sum.h ifndef mysum define mysum...
linux簡單實現靜態鏈結和動態鏈結
在給別人傳送檔案的時候,如果我們只想讓別人呼叫功能而已,不想自己的源 公布出去,我們可以選擇將檔案做成乙個庫,直接供別人呼叫就可以了。這樣的話,在網路上分享自己的勞動成果的話,只要傳送乙個鏈結庫和對應的標頭檔案 h 就足以 前提是確保 已經千錘百鍊過,不然除了問題別人沒辦法解決 靜態庫和動態庫 st...