靜態庫與共享庫

2021-08-04 12:39:51 字數 3107 閱讀 1281

1.

靜態庫:

所有編譯器都提供一種機制,將所有相關的目標檔案模組兒打包成乙個單獨的檔案,被稱為靜態庫。它可以用作來聯結器的輸入,當聯結器構造乙個輸入的可執行檔案時,它只拷貝靜態庫裡面被應用程式引用的模組兒。

在unix

系統中,靜態庫以存檔(一組連線起來的可重定位目標檔案的集合,有乙個頭部來描述成員目標檔案的大小和位置)的檔案格式存在於磁碟中。

使用靜態庫的例子:

(1)addvec.c

檔案void addvec(int *x,int *y,int *z,int n)

(2)multvec.c檔案:

void multvec(int *x,int *y,int *z,int n)

(3)用

vector.h

檔案宣告兩個函式的原型:

void addvec(int *x,int *y,int *z,int n);

void multvec(int *x,int *y,int *z,int n);

(4)用

ar工具建立靜態庫

libvector.a:

gcc–c addvec.c multvec.c

arrcs libvector.a addvec.o multvec.o

(5)main.c

檔案:#include

#include"vector.h"

int main()

;inty[2]=;

intz[2];

addvec(x,y,z,2);

printf("z=[%d %d]\n",z[0],z[1]);

return0;

}(6)

編譯執行:

gcc –o2 –c main.c

gcc –static –o p2 main.o ./libvector.a

-static

引數是告訴編譯器驅動程式,聯結器應該構建乙個完全鏈結的可執行目標檔案,它可以載入到儲存器並執行,在載入時無需更進一步的來鏈結。 2

:共享庫:(

動態鏈結由動態聯結器執行

)共享庫也稱為共享目標,在

unix

系統中用

.so字尾表示,微軟中使用共享庫陳偉

dll(動態共享庫);

共享庫的兩種共享方式:(

1)在任何系統中,對於乙個庫只有乙個

.so檔案,所有引用該庫的可執行目標檔案共享這個

.so檔案中的**和資料,而不是像靜態庫一樣將引用的內容拷貝和嵌入到可執行程式中。(

2)在儲存器中,乙個共享庫的

.text

節的乙個副本可以被不同的正在執行的程序共享。

1)在應用程式執行之前,也就是說在應用程式被載入的時候,動態載入器載入和鏈結任意共享庫(

2)應用程式在執行時要求動態載入器載入和鏈結任意共享庫,而無須在編譯時鏈結哪些庫到應用中。(

unix

提供了乙個介面,允許應用程式在執行時載入和鏈結共享庫)

#include

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

成功返回控制代碼的指標,失敗返回

null.

flag

引數:(1)rtld_now:

告訴聯結器立即解析對外部符號的引用。

(2)rtld_lazy:

高速聯結器推遲符號解析直到執行來自庫中的**。

#include

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

成功返回指向符號的指標,出錯為

null

,第一引數是前面已經開啟的共享庫的控制代碼,第二個引數是乙個符號的名字

#include

intdclose(void *handle);

成功返回

0,出錯返回

-1,沒有其他共享庫正在使用這個共享庫,

dlclose

函式就解除安裝該共享庫

#include

constchar *dlerror(void);

對於dlopen,dlsym,dlclose

的呼叫失敗,則返回出錯資訊,成功,則返回

null

例子:(1)

生成共享庫

:gcc –shared –fpic –o libvector.so addvec.cmultvec.c

-fpic

:告訴編譯器生成與位置無關的**。

(2)main1.c

檔案:#include

#include

#include

intx[2]=;

inty[2]=;

intz[2];

intmain()

/*get a pointer to the addvec() function wejust loaded*/

addvec = dlsym(handle,"addvec");

if((error = dlerror()) != null)

/*now we can call addvec() just like anyother function*/

addvec(x,y,z,2);

printf("z = [%d%d]\n",z[0],z[1]);

/*unload the shared library*/

if(dlclose(handle) < 0)

}(3)

執行編譯:

gcc –rdynamic –o2 p3 main1.c –ldl

–rdynamic

引數,告訴編譯器,對於符號解析而言,全域性符號也可用。

注意:如

gcc -0 p2 main1.c./libvector.a

,建立乙個

p2的慕白哦檔案。這個檔案執行時可以和

libvector.a

鏈結。建立可執行檔案時,靜態執行一些鏈結,程式載入時,動態完成鏈結過程。

載入器載入執行

p2時,

p2包含乙個

.interp

節,這個節包含動態聯結器的路徑名。載入器並不是將控制交給應用程式,而是載入和執行動態聯結器。

然後動態聯結器完成重定位任務,再將控股之傳遞給應用程式。

靜態庫與共享庫

編寫使用靜態庫 靜態庫 共享庫 是包含了目標檔案的檔案,這些目標檔案被稱為模板或成員,是可以重用的預編譯 它們以特殊的格式和乙個表或者對映儲存在一起,這個表或者對映將符號名和儲存該符號的成員名字鏈結起來。對映加速了編譯和鏈結過程,靜態庫一般以副檔名.a 代表存檔檔案,archive 命名。為了使用庫...

靜態庫與共享庫

庫library 靜態庫在編譯連線時就把庫里的 提取出來放入可執行檔案中,程式執行時不再依賴庫。動態庫在編譯連線時只記錄了要用的名字在哪個庫的檔案中,執行時才庫檔案中找這個檔案中名字 函式或變數 並且訪問它 1 靜態庫 歸檔 lib a 1 生成庫 gcc c 1.c 2.c 只編譯不連線,產生.o...

靜態庫與共享庫

庫是預先編譯好的方法的結合,是由二進位制可執行 組成,可以被載入記憶體中執行。在linux平台,庫通常放在 lib或者 usr lib中。命名 lib a 檔案格式 由眾多的可執行檔案 o 的打包 整合特點 在鏈結階段,會把整個庫中的 整合到程式中,所以最終編譯的可執行程式的大小比較大,但好處是編譯...