Linux下動態庫和靜態庫的製作及使用

2021-09-09 06:22:43 字數 3492 閱讀 1958

在實際的開發過程中,編寫程式往往都需要依賴很多基礎的底層庫,比方說平時用的較多的標準c庫,數學庫等等;我們會頻繁的使用這些庫里的函式,這些函式大多數都是前人為我們寫好的,所以值得慶幸的是我們的工作不必從零開始,我們要做的只是在恰當的位置呼叫合適的庫函式去實現相應的功能,充分利用前人的勞動成果,就是「站在巨人的肩膀上」。本文主要簡述linux下庫的製作以及使用方法。

一、什麼是庫

靜態庫的**在編譯過程中已經被載入可執行程式,因此體積較大。

共享庫的**是在可執行程式執行時才載入記憶體的,在編譯過程中僅簡單的引用,因此**體積較小。

二、初識靜態庫與動態庫

1.靜態函式庫

這類庫的名字一般是lib***.a,***為庫的名字。利用靜態函式庫編譯成的檔案比較大,因為整個函式庫的所有資料都會被整合進目標**中,他的優點就顯而易見了,即編譯後的執行程式不需要外部的函式庫支援,因為所有使用的函式都已經被編譯進去了。當然這也會成為他的缺點,因為如果靜態函式庫改變了,那麼你的程式必須重新編譯。

2.動態函式庫

這類庫的名字一般是lib***.m.n.so,同樣的***為庫的名字,m是庫的主版本號,n是庫的副版本號。當然也可以不要版本號,但名字必須有。相對於靜態函式庫,動態函式庫在編譯的時候並沒有被編譯進目標**中,你的程式執行到相關函式時才呼叫該函式庫裡的相應函式,因此動態函式庫所產生的可執行檔案比較小。由於函式庫沒有被整合進你的程式,而是程式執行時動態的申請並呼叫,所以程式的執行環境中必須提供相應的庫。動態函式庫的改變並不影響你的程式,所以動態函式庫的公升級比較方便。linux系統有幾個重要的目錄存放相應的函式庫,如/lib /usr/lib。

三、靜態庫與動態庫的比較

靜態庫其實從某種意義上來說只不過它操作的物件是目標**而不是原始碼而已。因為靜態庫被鏈結後庫就直接嵌入可執行檔案中了,這樣就帶來了兩個問題。

(1)首先就是系統空間被浪費了。這是顯而易見的,想象一下,如果多個程式鏈結了同乙個庫,則每乙個生成的可執行檔案就都會有乙個庫的副本,必然會浪費系統空間。

(2)再者,一旦發現了庫中有bug,挽救起來就比較麻煩了。必須一一把鏈結該庫的程式找出來,然後重新編譯。

而動態庫的出現正彌補了靜態庫的以上弊端。因為動態庫是在程式執行時被鏈結的,所以磁碟上只須保留乙份副本,因此節約了磁碟空間。如果發現了bug或要公升級也很簡單,只要用新的庫把原來的替換掉就行了。

但是靜態庫也有自己的優點:編譯後的執行程式不需要外部的函式庫支援,因為所有使用的函式都已經被編譯進去了。

四、如何判斷乙個程式有沒有鏈結動態庫

(1)file命令

file程式是用來判斷檔案型別的,啥檔案一看都清楚明了。

(2)ldd命令

看動態庫,如果目標程式沒有鏈結動態庫,則列印「not a dynamic executable」 (不是動態可執行檔案)

五、靜態庫的製作

(1) 為pr1和pr2生成object檔案

gcc -o -c pr1.c pr2.c

(2) ls

(3) 鏈結靜態庫

為了在編譯程式中正確找到庫檔案,靜態庫必須按照 lib[name].a 的規則命名,如下例中[name]=pr.

ar引數意義:

c: create的意思

r:在庫中插入模組(替換)。當插入的模組名已經在庫中存在,則替換同名的模組。

s:寫入乙個目標檔案索引到庫中,或者更新乙個存在的目標檔案索引。

v:該選項用來顯示執行操作選項的附加資訊。

t:顯示庫的模組表清單。一般只顯示模組名。

ar -crsv libpr.a pr1.o pr2.o

ar -t libpr.a //顯示靜態庫所依賴的檔案

(4) 編譯鏈結選項

-l 及-l 引數放在後面.其中,-l 載入庫檔案路徑,-l 指明庫檔案名字.

gcc -o main main.c -l./ -lpr //生成main

-i後面接頭檔案 (大寫的i)

-l後面接庫檔案路徑路徑

-l後面接庫檔名,除了「lib」和「.a」部分,全名為libpr.a

(5)執行目標程式

./main

六、動態庫的製作

(1)生成動態庫 ***.so

gcc -fpic -wall -c pr1.c

pic告訴編譯器產生與位置無關**(position-independent code), 則產生的**中,沒有絕對位址,全部使用相對位址,故而**可以被載入器載入到記憶體的任意位置,都可以正確的執行。這正是共享庫所要求的,共享庫被載入時,在記憶體的位置不是固定的。

gcc -shared -o libpr.so pr1.o

or use one line:

gcc -o -fpic -shared -o libpr.so pr1.c

(2)編譯時呼叫動態庫

gcc -o test main.c –l. -lpr

採用該方法執行會報告./test: error while loading shared libraries: libpr.so: cannot open shared object file: no such file or directory

原因:因為在動態函式庫使用時,會查詢/usr/lib、/lib目錄下的動態函式庫,而此時我們生成的庫不在裡邊。

這個時候有好幾種方法可以讓他成功執行:

(1)最直接最簡單的方法就是把so拉到/usr/lib或/lib中去,但這好像有點汙染環境吧。需要root許可權,在別人的電腦上會很麻煩;會把系統目錄弄得混亂。

(3)export ld_library_path=/tmp

不過這樣export 只對當前shell有效,當另開乙個shell時候,又要重新設定。可以把export ld_library_path=/tmp 語句寫到 ~/.bashrc中,這樣就對當前使用者有效了,寫到/etc/bashrc中就對所有使用者有效了。

echo $ld_library_path

不過ld_library_path的設定作用是全域性的,過多的使用可能會影響到其他應用程式的執行,所以多用在除錯。

小結:

總而言之,靜態庫是以空間換時間,動態庫是以時間換空間。無論你是在linux平台還是windows平台下做開發,庫的使用都大同小異。熟練的使各種庫,會給我們帶來許多便利,減少工作的負擔加快工程的進度,從此公升職,加薪不是夢,希望對你有所幫助。

Linux下的動態庫和靜態庫

靜態庫 程式編譯時載入,可執行程式體積大。一般命名為lib x.a。動態庫 程式執行時載入,可執行程式體積小。一般命名為lib x.so.1.3。x一般指庫名,如libxml2 tinyxml等 動態庫一般預設安裝在 lib 或者 usr lib 或者 usr local lib下。如果安裝的庫不在...

linux下的動態庫和靜態庫

1 使用gcc建立和使用靜態庫 1 gcc o mylib.o c mylib.c 生成o檔案 2 ar rcs libmylib.a mylib.o 生成a檔案 c create的意思 r replace的意思,表示當插入的模組名已經在庫中存在,則替換同名的模組。3 cp libmylib.a u...

Linux下的動態庫和靜態庫

1 使用gcc建立和使用靜態庫 1 gcc o mylib.o c mylib.c 生成o檔案 2 ar rcs libmylib.a mylib.o 生成a檔案 c create的意思 r replace的意思,表示當插入的模組名已經在庫中存在,則替換同名的模組。3 cp libmylib.a u...