靜態庫和動態庫

前言


在平時,我們很少關注於編譯和鏈接的過程,在現在IDE遍佈的天下,IDE爲我們考慮好了一切。但是真正的藏在每個程序運行背後的東西,很多系統軟件背後的運行機制都是需要我們去熟悉的,熟悉了這些,我們才能快速的解決一些相關的性能等問題。

大家應該都知道對於鏈接來說,應用程序有兩種的鏈接方式,一種就是靜態鏈接,一種是動態鏈接。

對於鏈接,鏈接的主要內容就是把各個模塊之間相互引用的部分都處理好,是的各個模塊之家能夠正確地銜接。鏈接過程主要包括了地址和空間的分配,符號決議和重定位等步驟。

靜態鏈接和動態鏈接

首先來說說靜態鏈接,靜態鏈接,指應用程序通過靜態鏈接的方式鏈接。靜態鏈接編譯的時候需要直接把代碼拷貝到調用處。所以程序可以獨立的執行,但是相對來說所佔大小更大。靜態鏈接的應用程序,不需要再次依賴庫,發佈的時候不需要帶着庫一塊發佈。

在linux當中,靜態鏈接的文件是.a的文件

動態鏈接,說的就是編譯的時候不直接拷貝可執行代碼,通過把動態庫加載到內存當中,然後程序去共享內存中的動態庫代碼。動態庫因爲不需要拷貝代碼,所以引用程序小,這樣節省空間。

linux下,.so是動態鏈接的文件。

我們通常也說A庫是靜態庫,SO是動態庫。

另外,兩種庫使用時間也有區別,靜態庫是在鏈接期間鏈接的,而動態庫是在程序執行的時候鏈接的。

庫:庫就是一種可執行代碼的二進制格式。可以被載入到內存中執行。

動態庫:
共享:多個應用程序可以使用同一個動態庫,啓動程序的時候,只需要將庫加載到內存當中。文件名一般爲lib.a。動態庫的代碼編譯的時候並沒有編譯進目標代碼,當執行到代碼的時候,纔會調用該動態庫。
靜態庫:
代碼裝載如引用程序,執行速度快,佔用內存。使用靜態庫的時候,鏈接器會去找程序當中相關的函數,然後拷貝到應用程序。
動態庫中包含了代碼和數據,動態庫的名稱一般爲如libc.so這樣的類型。

動態加載和卸載的庫

動態加載:編譯期間可以對動態庫的存在一無所知,而是在運行期間通過用戶程序嘗試加載進來的。

linux下的標準庫鏈接的三種方式:全靜態,半靜態,全動態

三種標準庫連接方式的選項和區別


標準庫鏈接方式 鏈接選項 優點 缺點
全靜態 -static -pthread
-lrt -ldl
不會發生程序在不同的版本下兼容問題 生成的文件大,並且生成的文件不能調用動態庫
全動態 -pthread -lrt -ldl 生成的文件是最小的 依賴庫生存,不同的版本下存在不兼容的問題
半靜態(libgcc,libstdc++) -static -libgcc -L
-pthread -lrt ldl
靈活度大,可以針對不同的標準庫採用不同的鏈接策略,結合全靜態和全動態兩種鏈接方式的優點。 難識別

半靜態鏈接,每次使用前還需要把符號鏈接到本地工程鏈接目錄。

示例鏈接選項中所涉及命令(引用 GCC 原文):


-llibrary
-l library:指定所需要的額外庫
-Ldir:指定庫搜索路徑
-static:靜態鏈接所有庫
-static-libgcc:靜態鏈接 gcc 庫
-static-libstdc++:靜態鏈接 c++ 庫

靜態庫和動態庫的製作使用


靜態庫:
使用靜態庫,操作是首先把代碼文件編譯爲.o目標文件。
然後通過ar工具將目標文件打包成.a靜態庫。
需要使用靜態庫的時候,只需要-L+文件路徑。
使用靜態庫。
首先我們可以寫三個文件,一個test.c和一個add.c文件,還有一個add.h文件,這三個文件可以實現加法函數,然後返回。
所以這個時候我們首先把add.c創建。

然後把add.c首先生成.o文件

gcc -c add.c

這樣就生成了add.c的目標文件,

然後我們利用ar指令我們生成靜態庫

ar -crv  libadd.a add.c

這個libadd.a文件就是靜態庫文件。
接下來我們就可以利用靜態庫文件鏈接鏈接生成應用程序

gcc -o test test.c libadd.a

這樣就生成了應用程序test。
另外鏈接我們也可以這樣:

gcc -o test test.c -ladd

這個時候的使用就是-l庫名的方式,這裏的庫名師除了庫函數庫和擴展名的字符串。這種方式需要去系統默認的路徑下查找庫,然後鏈接到應用程序上的。所以這種方式通常都需要去指定庫目錄。
gcc -o test test.c -L ./ -ladd

動態庫
使用動態庫,動態庫的使用,我們依然拿上面的例子來進行介紹,
我們依然使用上面的文件add.c,add.h,test.c。這三個文件依然可以實現動態庫。

首先我們和靜態庫一樣生成一個add.c的目標文件.o文件

gcc -fpic -c add.c

然後生成動態庫

gcc -shared -o libadd.so

注意生成的是動態庫文件,所以這裏是.so文件。

然後是使用動態庫鏈接。

gcc -o test test.c -L ./ -ladd

這個就是利用動態庫實現動態鏈接,-L說的是dog太鏈接庫的路徑,-ltiger是調用鏈接庫函數。

程序應該會提示錯誤,這是因爲在linux下動態鏈接庫是需要在系統目錄下才行,所以我們需要把動態鏈接拷貝到lib文件夾中,這樣就可以執行應用程序了。

另外的一種方法就是修改環境變量,這樣就讓動態鏈接庫可以看到當前目錄。
比如:

export LD_LIBRARY_PATH =.
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章