靜態庫和共享庫

2021-04-19 09:38:28 字數 4291 閱讀 9133

建立和使用靜態庫

1. 建立目錄

mkdir –p test/sub

2. 在子目錄sub/下編寫hello.c和hello.h

/*****hello.c*****/

#include

#include 「hello.h」

void hello()

/*****hello.h*****/

#include

void hello();

4. 在主目錄test/下編寫main.c

#include

#include 「sub/hello.h」

int main()

5. 編譯鏈結

gcc –c main.c –o main.o

gcc main.o –o main.exe –l 「sub/」 –lhello          #dynamically linked (uses shared libs)

或gcc main.o –o main.exe –static –l 「sub/」 –lhello  # statically linked

.a(archive)  靜態庫   

.so(shared object) 共享庫

靜態庫只在程式鏈結時起作用,最終的執行程式脫離靜態庫執行。

共享庫在程式執行時起作用。

共享庫的編號約定

格式library_name.major_num.minor_num.patch_num

例如libminigui.so.2.0.0

major_num:當庫的變化達到了和以前的版本不能相容的成都時就要增加主版本號

minor_num:當庫有了新變化又能和以前的版本保持相容時就只改變次版本號

patch_num:為修正庫中的錯誤而進行的改動則會改變補丁級別號,它又叫做發行號(release number)。

以_g和_p結尾的庫:

例如libminigui_g.a和libminigui_p.a

它們是基本庫的特殊版本,基本庫為libminigui.a。以_g結尾的庫是除錯庫,編入了特殊的符號和功能,增加了對採用了這個庫的應用程式的除錯功能。以_p結尾的庫是**剖析庫(profiling),它們包含的**和符號能進行複雜的**剖析和效能分析。你如果使用了這兩類庫,一旦完成了除錯和剖析工作,需要使用正常庫重新編譯你的程式。

庫操作的相關命令

nm功能

列出編入目標檔案或二進位制檔案的所有符號。用途一:檢視程式呼叫什麼函式;用途二:檢視乙個給定的庫或目標檔案是否提供了所需的函式。

語法nm [options] file

常用選項

-c 將符號名轉換為使用者級的名字。在讓c++函式名可讀方面特別有用。

-s 當用於.a檔案時,輸出把符號名對映到定義該符號的模組或成員名的索引。

-u 只顯示未定義的符號,即在被檢查的檔案外部定義的檔案。

-l  使用除錯資訊輸出定義每個符號的行號,或未定義符號的重要位項。

ar功能

將多個.o檔案組合到一起成為.a檔案。

語法ar [options] lib*.a *.o

常用選項

-c 如果存檔檔案不存在,則建立,並不顯示ar發出的警告。

-q 把*.o新增到存檔檔案末尾而不檢查是否進行替換。

-r  向存檔檔案中插入.o檔案,替換已有的任何同名檔案,新成員新增到文件末尾。

-s 建立或公升級從符號到.a檔案之間的交叉索引對映表,並加入到.a檔案中。

等價與ranlib [*.a]。執行該命令後,可用nm –s來檢視生成的索引。

ldd功能

顯示可執行程式執行所需的共享庫。

語法ldd [options] file

常用選項

-d 執行重定位並報告所有丟失的函式。

-r 執行對函式和資料物件的重定位並報告丟失的任何函式或資料物件。

ldconfig

功能在預設搜尋目錄(/lib和/usr/lib)及動態庫配置檔案/etc/ld.so.conf中所列的目錄下,搜尋出可共享的動態鏈結庫(lib*.so*),進而建立出動態裝入程式(ld.so)所需的連線和快取檔案。快取檔案預設為 /etc/ld.so.cache,此檔案儲存了已排好序的動態鏈結庫名字列表。

該在系統啟動時會執行,而當使用者安裝了乙個新的動態鏈結庫時,就需要手工執行這個命令。

語法ldconfig [options] path

例如:ldconfig /root/lib 讓系統共享/root/lib目錄下的動態鏈結庫,即在/etc/ld.so.cache中新增指定目錄下的共享庫。[注意]若該目錄不在/lib,/usr/lib,/etc/ld.soconf所列的目錄列表裡,則再次執行ldconf時,此目錄下的動態鏈結庫就不被系統共享了。

常用選項

-v 更新/etc/ld.so.cache的內容,列處每個庫的版本號,掃瞄的目錄和所有建立和更新的鏈結。

-p 僅顯示/etc/ld.so.cache的內容,即ld.so所知道的共享庫的當前列表。

-n  ldconf僅掃瞄-n命令所指定的目錄

-f conf   指定動態鏈結庫的配置檔案為conf,系統預設為/etc/ld.so.conf。

-c cache  指定生成的快取檔案為cache,系統預設為/etc/ld.so.cache。

當ldconf不帶選項時,僅更新高速緩衝檔案。 

環境變數

$ld_preload      由空格分隔的共享庫列表,在其它庫之前載入,使它們有機會覆蓋或

重新定義標準庫。

$ld_library_path 由冒號分隔的目錄清單,都是共享庫搜尋時會訪問的目錄。

建立和使用動態庫

建立動態庫

1. gcc –fpic –c hello.c –o hello.o

2. gcc –shared –wl,-soname,libhello.so –o libhello.1.0.0 hello.o –lc

引數說明

-fpic   產生與位置無關的**,並能載入到任何位置。-fpic與之相似,會生成更小更快的

**,但會有平台的限制。

-shared  告訴編譯器生成共享庫**。

-wl     告訴編譯器將後面的引數傳給鏈結器ld。

-soname 指定了共享庫的簡寫共享名(short for shared object name)。

-l       指定鏈結的庫檔名。

-l      向gcc的庫檔案搜尋路徑中新增新的目錄

使用動態庫

方法一1) 將生成的.so檔案複製到系統預設的存放庫檔案的資料夾,如/usr/lib。如果你複製

libhello.so.1.0.0到/usr/lib,會自動生成乙個它的符號鏈結libhello.so。

2) 以root身份執行ldconfig,更新高速緩衝區/etc/ld.so.cache。

3) gcc –c main.c –o main –lhello

方法二1) 改變環境變數$ld_library_path=」your dir」

2) gcc –c main.c –o main –l 「sub」 –lhello

方法三1) 在/etc/ld.so.conf中新增你的共享庫所在的路徑

2) 以root使用者身份執行ldconfig

3) gcc –c main.c –o main –l 「sub」 -lhello

使用動態載入的共享物件

只需在原始碼中包含,然後在編譯命令或makefile中使用-ldl命令與libdl庫鏈結即可。

[注意]不必鏈結你要使用的庫。即使使用乙個標準的共享庫,也不必按常規方法使用,鏈結器不會知道共享物件。在編譯鏈結應用程式時,這些模組甚至可以不存在。

dlopen

載入共享物件。如果找到了filename就返回控制代碼,否則返回null。

void *dlopen (const char *filename, int flag);

dlsym

使用共享物件。dlsym在載入物件(由handle指向的共享物件)中搜尋在symbol中命名的符號或函式。引數handle須是dlopen返回的控制代碼;引數symbol是乙個標準的c字串。dlsym

返回指向符號的空指標,若發生錯誤則返回null。

void *dlsym (void *handle, char *symbol)

dlerror

檢查錯誤。如果任何函式出錯,dlerror返回乙個描述錯誤的字串,再把錯誤的字串置為null。

const char *dlerror (void);

dlclose

解除安裝共享庫。確定不再需要某個共享物件後,關閉它以節省系統資源。

int dlclose (void *handle);

靜態庫和共享庫(二)

brary值 2 動態鏈結緩衝檔案 etc ld.so.cache 3 目錄 lib,usr lib flag表示在什麼時候解決未定義的符號 呼叫 取值有兩個 1 rtld lazy 表明在動態鏈結庫的函式 執行時解決.2 rtld now 表明在dlopen返回前就解決所有未定義的符號,一旦未解決...

靜態庫和共享庫概念

1.靜態庫和共享庫的概念 在鏈結共享庫時只是指定了動態鏈結器和該程式所需要的庫檔案,並沒有真正的做鏈結,可執行檔案中仍然是未定義的符號,需要在執行時做動態鏈結。而在鏈結靜態庫時,鏈結器會把靜態庫中的目標檔案取出來和可執行檔案真正的鏈結在一起,所以採用靜態庫的可執行檔案一般很大,不需要庫檔案也能執行,...

靜態庫和共享庫的區別

根據鏈結時期不同,庫分為靜態庫和動態庫。靜態庫是在程式編譯時鏈結的,動態庫是在程式執行時鏈結的。庫是預先編譯好的方法的集合 linux上庫的命名一般為lib a 靜態庫 lib so 動態庫 庫檔案常存放的地點為 lib或 usr lib,庫對應的標頭檔案一般存放在 usr include中 下面介...