動態鏈結和靜態鏈結

2021-07-27 03:59:41 字數 2168 閱讀 4210

庫從本質上來說是一種可執行的二進位制檔案,可以被載入到記憶體中執行,而根據鏈結時期的不同,庫又可以分為靜態庫和動態庫。

靜態鏈結就是在編譯時將多個目標檔案組合在一起形成乙個可執行檔案的過程。

1.空間與位址的分配過程中,首先會掃瞄所有的輸入檔案,獲得他們的各個段的長度,屬性和位置,然後將輸入檔案中所有的符號定義和符號引用收集起來,統一放到乙個全域性符號表中,在合併相應的段,計算出合併後的段的長度和位置,並建立相應的對映關係。

2.符號解析與符號重定位:這個過程是鏈結的核心,它讀入輸入檔案中的段資訊,重定位資訊,並進行符號解析和重定位,調整**中的位址,進而完成鏈結。

動態鏈結的引入是為了解決靜態鏈結過程中的空間浪費以及程式庫公升級不方便的問題,它本質上是一種載入時鏈結的技術,把程式的符號解析和重定位推遲到載入的時候再進行。

鏈結中重要的乙個問題就是重定位,即修改**段,將全域性變數和外部函式的位址替換成執行時的真實位址,在動態鏈結中,採用了位址無關**技術,該技術的主要思想是把**段中跟位址相關的部分放到資料段中,使得重定位時,**段不需要被修改。這個思想依賴於下面兩個事實:

1.無論何處載入乙個共享庫,其資料段總是緊跟在**段之後的,即**段中任何指令和資料段中任何變數之間的距離都是乙個常量,與**段和資料段的絕對位址無關。

2.目標模組的資料段,在各個程序中都有對應的副本,是可以被修改的。

於是,編譯器在資料段開始的地方建立了乙個全域性偏移量表,記錄了該模組外所有外部函式或全部變數的表目,同時為全域性偏移量表中每個表目生成乙個重定位記錄,在載入時,動態鏈結器更新got中表目的值,使得其值為該符號的執行時絕對位址。

函式的延遲繫結

動態鏈結中乙個降低程式效能的原因是動態鏈結的工作是在載入時完成的,即程式啟動後動態鏈結庫要完成鏈結過程,即需要尋找並加在所需的共享庫,進行符號搜尋和重定位,這樣無疑會影響程式的啟動速度,於是就有了延遲繫結技術。

首先檔案的字尾不一樣,在linux系統中靜態庫的檔案字尾為.a,動態庫的檔案字尾為.so

靜態庫檔案的大小較大,動態庫檔案的大小較小;

靜態庫是將庫中的**拷貝到自己的**中,這樣將自己的**拷貝到**都可以執行;

在生成靜態庫檔案前,我們首先要通過指令gcc -c ***.o ***.c生成產生靜態庫檔案的輸入檔案。

然後,我們通過ar cr lib***.a ***.o生成靜態庫檔案(靜態庫)。

隨後就是通過gcc鏈結生成可執行檔案,通過gcc -o *** test.c -static -l*** -l.

注意首先必須是靜態鏈結,所以要加-static選項,然後又因為我們是在當前目錄下生成的靜態庫檔案,所以我們加上-l.選項使gcc在當前目錄下尋找靜態庫檔案。

整個過程如下圖所示:

在動態鏈結可執行程式前,首先我們要生成動態庫檔案,我們可以使用gcc -shared -fpic -o lib***.so ***.o生成動態庫檔案;

然後,我們進行鏈結過程生成可執行檔案gcc -o *** test.c -l*** -l.

我們先來看看結果:

我們發現動態庫libmyadd.so檔案成功生成,但是程式卻無法執行。

這是因為gcc對動態庫的查詢是根據環境變數ld_library_path中所指定的路徑來進行查詢的,由於我們的動態庫生成在當前目錄下,所以我們還沒有把當前目錄新增到環境變數中,所以無法找到動態庫檔案。

我們新增後來檢視下結果:

我們發現這是動態鏈結的檔案執行沒有任何問題了~

動態鏈結和靜態鏈結

在類的習慣性用法中,我們提到 對於類中 量較多的成員函式,僅僅在標頭檔案的類中宣告成員和函式用法,而將方法封裝起來。對於 量較大的成員函式來說,直接把 放在類中定義存在兩個問題 一是使用起來很不方便,二是破壞了資訊隱藏機制。那麼為什麼說將 放在類中定義會破壞資訊隱藏機制呢?實際上,對於變數和函式,一...

動態鏈結和靜態鏈結

作為一名c c 程式設計師,對於編譯鏈結的過程要了然於胸。首先大概介紹一下,編譯分為3步,首先對原始檔進行預處理,這個過程主要是處理一些 號定義的命令或語句 如巨集 include 預編譯指令 ifdef等 生成 i檔案 然後進行編譯,這個過程主要是進行詞法分析 語法分析和語義分析等,生成 s的彙編...

動態鏈結和靜態鏈結的區別

動態鏈結和靜態鏈結的區別 一 分別編譯與鏈結 linking 大多數高階語言都支援分別編譯,程式設計師可以顯式地把程式劃分為獨立的模組或檔案,然後每個獨立部分分別編譯。在編譯之後,由鏈結器把這些獨立的片段 稱為編譯單元 粘接到一起 想想這樣做有什麼好處?在c c 中,這些獨立的編譯單元包括obj檔案...