Linux下鏈結動態庫靜態庫的理解

2021-06-09 06:52:26 字數 2861 閱讀 1699

linux程式gcc編譯基本過程

乙個程式從原始碼到可執行檔案(或共享庫檔案),一般都要經過預處理、編譯、彙編和鏈結這四個步驟。

編譯過程掃瞄標頭檔案的搜尋路徑順序

gcc 在編譯時如何去尋找所需要的標頭檔案 :

※所以header file的搜尋會從-i開始

※然後找gcc的環境變數 c_include_path,cplus_include_path,objc_include_path

※再找內定目錄

/usr/include

/usr/local/include

/usr/lib/gcc-lib/i386-linux/2.95.2/include

/usr/lib/gcc-lib/i386-linux/2.95.2/../../../../include/g++-3

/usr/lib/gcc-lib/i386-linux/2.95.2/../../../../i386-linux/include

庫檔案但是如果裝gcc的時候,是有給定的prefix的話,那麼就是

/usr/include

prefix/include

prefix/***-***-***-gnulibc/include

prefix/lib/gcc-lib/***x-***-***-gnulibc/2.8.1/include

尤其注意鏈結過程是本文要重點討論的:

鏈結步驟要經歷鏈結內部庫(即當前程式原始碼編譯而成的.a,.o,.so)和外部庫(依賴的外部靜態lib.a、動態庫lib.so)

外部庫外部庫有兩種: (1)靜態連線庫lib.a

(2)共享連線庫lib.so

共同點:

.a, .so都是.o目標檔案的集合,這些目標檔案中含有一些函式的定義(機器碼),而這些函式將在連線時會被最終的可執行檔案用到。

區別:靜態庫.a  : 當程式與靜態庫連線時,庫中目標檔案所含的所有將被程式使用的函式的機器碼被copy到最終的可執行檔案中。

共享庫.so : 與共享庫連線的可執行檔案只包含它需要的函式的表,而不是所有的函式**,在程式執行之前,那些需要的函式**被拷貝到記憶體中,這樣就使可執行檔案比較 小,節省磁碟空間(更進一步,作業系統使用虛擬記憶體,使得乙份共享庫駐留在記憶體中被多個程式使用)。共享庫還有個優點:若庫本身被更新,不需要重新編譯與 它連線的源程式。

linux下庫是如何產生的

靜態庫的字尾是.a,它的產生分兩步

step 1.由原始檔編譯生成一堆.o,每個.o裡都包含這個編譯單元的符號表

step 2.ar命令將很多.o轉換成.a,成文靜態庫

動態庫的字尾是.so,它由gcc加特定引數編譯產生。

例如:$ gcc -fpic -c *.c $ gcc -shared -wl,-soname, libfoo.so.1 -o libfoo.so.1.0 *.

linux下庫檔案是如何命名的,如何存放

靜態庫的名字一般為lib***x.a,其中***x是該lib的名稱

動態庫的名字一般為lib***x.so.major.minor,***x是該lib的名稱,major是主版本號, minor是副版本號

linux下,庫檔案一般放在/usr/lib /lib下,

如果安裝在/lib或者/usr/lib下,那麼ld預設能夠找到,無需其他操作。

如果安裝在其他目錄,需要將其新增到/etc/ld.so.cache檔案中,步驟如下

2.執行ldconfig,該命令會重建/etc/ld.so.cache檔案

linux中有關編譯鏈結要是用的庫掃瞄路徑,與有關環境變數

靜態庫鏈結時搜尋路徑順序:

1.ld會去找gcc命令中的引數-l

2.再找gcc的環境變數library_path

3.再找內定目錄 /lib /usr/lib /usr/local/lib 這是當初compile gcc時寫在程式內的

動態鏈結時、執行時搜尋路徑順序:

1.編譯目標**時指定的動態庫搜尋路徑;

2.環境變數ld_library_path指定的動態庫搜尋路徑;

3.配置檔案/etc/ld.so.conf中指定的動態庫搜尋路徑;

4.預設的動態庫搜尋路徑/lib;

5.預設的動態庫搜尋路徑/usr/lib。

有關環境變數:

library_path環境變數:指定程式靜態鏈結庫檔案搜尋路徑

ld_library_path環境變數:指定程式動態鏈結庫檔案搜尋路徑

鏈結過程

建立靜態庫方法(包括靜態內部庫和動態外部庫)

gcc -c fun.c

ar cqs libfun.a fun.o

編譯中使用靜態庫方法

gcc call.c -static -l. -lfun -o fun_static_call

建立動態庫(包括動態內部庫和動態外部庫)

gcc fun.c -fpic -shared -o libfun.so

編譯中使用動態庫方法

gcc call.c -l. -lfun -o fun_dyn_call

執行過程

無論是使用動態庫還是外部庫鏈結時都是使用的ld聯結器;

使用動態庫的程式執行時使用動態載入器。在linux 下,載入器是/lib/ld-linux.so.x(x是版本號)。然後載入器搜尋、引導程式所要使用的動態鏈結庫。搜尋順序見上。

檢視庫中的符號

有時候可能需要檢視乙個庫中到底有哪些函式,nm命令可以列印出庫中的涉及到的所有符號。庫既可以是靜態的也可以是動態的。nm列出的符號有很多,常見的有三種:

一種是在庫中被呼叫,但並沒有在庫中定義(表明需要其他庫支援),用u表示;

一種是庫中定義的函式,用t表示,這是最常見的;

另外一種是所謂的「弱 態」符號,它們雖然在庫中被定義,但是可能被其他庫中的同名符號覆蓋,用w表示。

linux下 GCC編譯鏈結靜態庫 動態庫

目錄 回到頂部 有時候需要把一組 編譯成乙個庫,這個庫在很多專案中都要用到,例如libc就是這樣乙個庫,我們在不同的程式中都會用到libc中的庫函式 例如printf 也會用到libc中的變數 例如以後 要講到的environ變數 本文將介紹怎麼建立這樣乙個庫。這些檔案的目錄結構是 tree mai...

Linux下動態鏈結庫和靜態鏈結庫

第一部分 編譯過程 預處理過程,負責標頭檔案展開,巨集替換,條件編譯的選擇,刪除注釋等工作。gcc e表示進行預處理。編譯過程,負載將預處理生成的檔案,經過詞法分析,語法分析,語義分析及優化後生成彙編檔案。gcc s表示進行編譯。彙編,是將彙編 轉換為機器可執行指令的過程。通過使用gcc c或者as...

linux下編譯 鏈結 裝載 動態庫和靜態庫的學習

linux下編譯 鏈結和裝載.自己在linux上編譯 鏈結 動態庫和靜態庫的學習筆記 編譯生成可執行檔案 我們在單獨編譯的時候,只需要檢查標頭檔案,因為都放到了乙個目錄,所以單獨編譯的時候,不需要依賴其他檔案,就可以生成目標檔案 o 如下 g c showcoor.cpp g c showpoint...