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