庫(kù)有動(dòng)態(tài)與靜態(tài)兩種,動(dòng)態(tài)通常用.so為后綴,靜態(tài)用.a為后綴。 例如:libtest.so libtest.a。為了在同一系統(tǒng)中使用不同版本的庫(kù),可以在庫(kù)文件名后加上版本號(hào)為后綴,但由于程序連接默認(rèn)以.so為文件后綴名。所以為了使用這些庫(kù),通常使用建立符號(hào)連接的方式。如:
ln -s libtest.so.1.0 hello.so.1
ln -s libtest.so.1 hello.so 下面對(duì)比一下兩者:
靜態(tài)鏈接庫(kù):當(dāng)要使用時(shí),連接器會(huì)找出程序所需的函數(shù),然后將它們拷貝到執(zhí)行文件,由于這種拷貝是完整的,所以一旦連接成功,靜態(tài)程序庫(kù)也就不再需要了。
動(dòng)態(tài)庫(kù)而言:某個(gè)程序在運(yùn)行中要調(diào)用某個(gè)動(dòng)態(tài)鏈接庫(kù)函數(shù)的時(shí)候,操作系統(tǒng)首先會(huì)查看所有正在運(yùn)行的程序,看在內(nèi)存里是否已有此庫(kù)函數(shù)的拷貝了。如果有,則讓其共享那一個(gè)拷貝;只有沒(méi)有才鏈接載入。在程序運(yùn)行的時(shí)候,被調(diào)用的動(dòng)態(tài)鏈接庫(kù)函數(shù)被安置在內(nèi)存的某個(gè)地方,所有調(diào)用它的程序?qū)⒅赶蜻@個(gè)代碼段。因此,這些代碼必須使用相對(duì)地址,而不是絕對(duì)地址。在編譯的時(shí)候,我們需要告訴編譯器,這些對(duì)象文件是用來(lái)做動(dòng)態(tài)鏈接庫(kù)的,所以要用地址不無(wú)關(guān)代碼(Position Independent Code (PIC))。注意:linux下進(jìn)行連接的缺省操作是首先連接動(dòng)態(tài)庫(kù),也就是說(shuō),如果同時(shí)存在靜態(tài)和動(dòng)態(tài)庫(kù),不特別指定的話(huà),將與動(dòng)態(tài)庫(kù)相連接。
下面就通過(guò)實(shí)際的例子來(lái)向大家演示一下,該怎樣編譯和使用靜態(tài)和動(dòng)態(tài)鏈接庫(kù),這里有一個(gè)頭文件:lib_test.h,一個(gè).c文件:lib_test.c:
1.編寫(xiě)庫(kù)文件lib_test.c 2.編寫(xiě)一個(gè)頭文件用于聲明我們使用的函數(shù)lib_test.h 3.用gcc編繹該文件,可以使用任何合法的編繹參數(shù)
#include<stdio.h> #ifndef _LIBTEST_H gcc -c lib_test.c -o lib_test.o
void a() #define _LIBTEST_H
{ void a();
printf("zyx\n"); #endif
}
下面就用上面的文件生成和使用靜態(tài)和動(dòng)態(tài)鏈接庫(kù):
(一)靜態(tài)鏈接庫(kù)
1)用gcc編繹該文件,可以使用任何合法的編繹參數(shù)
gcc -c lib_test.c -o lib_test.o
2) $ar crv libtest.a lib_test.o //生成靜態(tài)庫(kù)生成libtest.a
3) 在某些系統(tǒng)中還要為靜態(tài)庫(kù)生成一個(gè)內(nèi)容表 $ranlib libtest.a
4) 使用靜態(tài)鏈接庫(kù)
$nm libtest.a //nm工具可以打印出庫(kù)中的涉及到的所有符號(hào),庫(kù)既可以是靜態(tài)的也可以是動(dòng)態(tài)的。nm列出的符號(hào)有很多, 常見(jiàn)的有三種,一種是在庫(kù)中被
調(diào)用,但并沒(méi)有在庫(kù)中定義(表明需要其他庫(kù)支持),用U表示;一種是庫(kù)中定義的函數(shù),用T表示,這是最常見(jiàn)的;另外一種是所謂的"弱態(tài)”
符號(hào),它們雖然在庫(kù)中被定義,但是可能被其他庫(kù)中的同名符號(hào)覆蓋,用W表示。
$gcc -c -I/home/xxxxxxxx main.c //假設(shè)main.c要使用對(duì)應(yīng)的靜態(tài)庫(kù)
$gcc -o main -L/home/xxxxxxxx main.o libtest.a
說(shuō)明:這里的-I/home/xxxxxxxx和-L/home/xxxxxxxx 是通過(guò)-I和-L指定對(duì)應(yīng)的頭文件和庫(kù)文件的路徑,libtest.a就是要用的靜態(tài)庫(kù)。在main.c中要包含靜態(tài)庫(kù)
的頭文件。
5)然后執(zhí)行程序就可以看到成功了。#./main
(二)動(dòng)態(tài)鏈接庫(kù) 可以依次使用下面的命令
1)$gcc -fPIC -o libtest.o -c lib_test.c
2)$gcc -shared -o libtest.so libtest.o
也可以直接使用一條命令gcc -fPIC -shared -o libtest.so lib_test.c
3)有兩種方法使用動(dòng)態(tài)鏈接庫(kù)。
a)#gcc -o main main.c ./libtest.so
b)先#cp ./libtest /usr/lib 然后gcc -o test test.c libtest.so這時(shí)要保證這個(gè)庫(kù)所在目錄包括再PATH 環(huán)境變量中。
4)然后執(zhí)行程序就可以看到成功了。#./main
最后說(shuō)一下庫(kù)的路徑問(wèn)題,算是結(jié)個(gè)尾吧:
動(dòng)態(tài)庫(kù)的搜索路徑搜索的先后順序是:
1.編譯目標(biāo)代碼時(shí)指定的動(dòng)態(tài)庫(kù)搜索路徑;
2.環(huán)境變量LD_LIBRARY_PATH指定的動(dòng)態(tài)庫(kù)搜索路徑;
3.配置文件/etc/ld.so.conf中指定的動(dòng)態(tài)庫(kù)搜索路徑;//只需在在該文件中追加一行庫(kù)所在的完整路徑如"/root/test/conf/lib"即可,然后ldconfig是修改生效。
4.默認(rèn)的動(dòng)態(tài)庫(kù)搜索路徑/lib;
5.默認(rèn)的動(dòng)態(tài)庫(kù)搜索路徑/usr/lib。
聯(lián)系客服