1 庫的生成和使用
庫可以有三種使用的形式:靜态、共享和動态。靜态庫的代碼在編譯時就已載入到開發人員開發的應用程式中。而共享庫在程式開始運作時才載入,在編譯時隻是簡單地指定需要使用的庫函數。動态庫則是共享庫的另一種變化形式,動态庫也是在程式運作時載入,但與共享庫不同的是,程式中使用到的庫函數不是在程式開始運作時,而是在程式中的語句需要使用該函數時才載入。動态庫可以在程式運作期間釋放動态庫所占用的記憶體,騰出空間供其它程式使用。
動态庫的字尾通常為.so (Shared Object),靜态庫的字尾通常為.a (Archive)。在預設情況下,共享庫通常為綠色,而靜态庫為黑色。
為了在同一系統中使用不同版本的庫,可以在庫檔案名後加上版本号為字尾,例如:libhello.so.1.0。但是由于程式連結預設以.so和.a為檔案字尾名,是以為了能夠正常使用這些庫,通常使用建立符号連結的方式。
ln-fs libhello.so.1.0 libhello.so
ln–fs libhello.a.1.0 libhello.a
/lib/ld.so:Linker andloader;
/etc/ld.so.conf:List of directories that contain libraries;
/etc/ld.so.cache:List of the libraries in libraries mentioned in/etc/ld.so.conf.
1.1 庫的生成
1.1.1 生成靜态庫
arkey [modifiers] [reference-member] archive [members]
隻有一個key可能被用到,但是一個key可以和多個modifiers聯合使用。reference-member是庫中已經存在的某一個成員的名字。
key
d :從庫中删除成員。
m :将成員移動到庫的末尾。
a,b,i可以影響該key的操作。
p :列印庫中的成員。
q :添加成員到庫的末尾,withoutchecking the replacement。
a,b,i并不能影響該key的操作。
r :替換庫中的成員,并把替換的成員移動到庫的末尾。
a,b,i可以影響該key的操作。
t :列出整個庫的内容或者是隻列出指定的成員。
x :從庫中提取所有成員或者是指定的成員。
modifiers
a :和r或者m一起使用在reference-member之後放置成員。
b/i :和r或者m一起使用在reference-member之前放置成員。
c :建立庫。
o :當提取成員時,保持成員原有的時間戳,否則将改變成員的時間戳為提取的時間。
s :Write an object-file index into the archive。
Running ar son an archive is equivalent to running ranlibon it。
S :禁止生成archive symbol table。
u :隻能和r一起使用,隻替換那些已經被更新的成員。
例如:
$arrc libhello.a.1.0 hello.o
$ln-fs libhello.a.1.0 libhello.a
1.1.2 生成動态庫
動态庫的生成由gcc來完成,通常指定版本号:
$gcc-shared -o libhello.so.1.0 hello.o -Wl,-soname, libhello.so.1.0
$ln-fs libhello.so.1.0 libhello.so
實際上每一個庫都有一個soname,在程式執行期間,程式會使用soname查找庫,而不是庫名。這樣的話在程式運作期間,可以有多個名字相同但soname不同的庫存在,而程式可以根據soname找到對應的庫檔案。
1.2 庫的使用
如果要使用一個庫(靜态庫libhello.a或動态庫libhello.so),則必須準備兩個檔案:一個就是庫檔案libhello.a或libhello.so;另外一個就是向使用者提供函數聲明的頭檔案(hello.h)。
假設hello.h中提供了sayhello()的函數聲明,而使用者編寫的test.c需要使用sayhello()函數:
#include“hello.h” // 必須儲存在頭檔案的搜尋路徑中
intmain( )
{
sayhello();
return 0;
}
1.2.1 靜态庫的使用
$gcc-o test test.c -Wl,-Bstatic –Ldir -lhello
靜态庫檔案隻在編譯連結時需要,可執行程式一旦編譯成功,則放在哪裡都可以運作,不再需要靜态庫檔案的支援。
1.2.2 動态庫的使用
$gcc-o test test.c –W1,-Bdynamic –Ldir –lhello
因為預設進行的就是動态庫連結,是以上面的指令可以簡寫為:
$gcc-o test test.c –Ldir –lhello
需要注意的是動态庫檔案不但在編譯連結時需要,即使可執行程式編譯成功,它的運作業需要動态庫檔案的支援,是以動态庫必須能夠被搜尋到,有兩種方法:
(1) 把動态庫檔案拷貝到/usr/lib和/lib目錄下。
(2) 修改/etc/ld.so.conf檔案,加入庫檔案所在的路徑,并執行ldconfig重新整理。
如果要和多個庫進行連結,而且每個庫的連結方式不一樣,其指令為:
$gcc-o test test.c –W1,-Bstatic –Ldir -lhello –W1,-Bdynamic –Ldir -lbye
1.3 庫的查詢
1.3.1 nm
nm列印出庫中所有的符号。庫既可以是靜态的也可以是動态的。nm列出的符号有:
A:absolute,will not be changed by future link。
B:the symbolis in the un-initialized data section。
C:the symbolis common,common symbols are in the un-initializeddata section。When linking,multiplecommon symbols may appear with the same name。
D:the symbolis in the initialized data section。
G:the symbolis in the initialized data section for small objects。
I:the symbolis an indirect reference to another symbol。
N:the symbolis a debugging symbol。
R:the symbolis in a read only data section。
S:the symbolis in a un-initialized data section for small objects。
T:the symbolis in the text(code) section。
U:the symbolis undefined。
V:the symbolis a weak object symbol。When a weak defined symbol is linked with anormal defined symbol,the normal defined symbol is used with noerror。When a weak undefined symbol is linked,the value of the weak symbol becomes zero with noerror。
W:the symbolis a weak symbol that has not been specifically tagged as a weak object symbol。When a weak defined symbol is linked with a normaldefined symbol,the normal defined symbol is used with noerror。When a weak undefined symbol is linked,the value of the weak symbol is determined in asystem-specific manner with no error。Uppercaseindicates that a default value has been specified。
-:the symboltype is unknown。
nm[options] [objfiles]
-a:列印所有的符号,包括debugonly符号(預設是不列印的)。
-A:列印每一個符号的所屬檔案名。
-C:将符号轉譯為可讀形式。
-D:隻列印dynamicsymbols。
-g:隻列印外部符号。
-u:隻列印未定義的符号。
--defined-only:隻列印定義過的符号。
-s:當列印庫成員的符号時,列印出它們的索引,也就是這些符号屬于哪個子產品。
-S:列印每一個定義過符号的大小,而不列印它們的值。
假設希望知道hello庫中是否定義了sayhello():
$nmlibhello.so | grep sayhello
1.3.2 ldd
ldd是LibraryDependency Display縮寫,它的作用是顯示一個可執行程式或一個共享庫必須使用的共享庫。
lddprograms/shared libraries
1.3.3 ldconfig
庫安裝到系統以後,為了讓動态連結庫為系統所認識及共享,就需要運作ldconfig。ldconfig指令的用途,主要是在預設搜尋目錄(/lib和/usr/lib)以及動态庫配置檔案/etc/ld.so.conf内所列的目錄下,搜尋出可共享的動态連結庫(格式如lib*.so*),進而建立出動态裝入程式(ld.so)所需的連結和緩存檔案。緩存檔案預設為/etc/ld.so.cache,此檔案儲存已排好序的動态連結庫的名字清單,ldconfig通常在系統啟動時運作,當使用者安裝了一個新的動态連結庫時,就需要手工運作這個指令:
ldconfig[options] [libs]
-n:僅掃描指令行指定的目錄,不掃描預設目錄(/lib、/usr/lib),也不掃描配置檔案/etc/ld.so.conf所列的目錄。
-fconf:使用conf檔案代替/etc/ld.so.conf
-Ccache:使用cache檔案代替/etc/ld.so.cache
-p:列印在目前cache中存放的目錄和庫檔案清單。
-N:Do not rebuild cache,links arestill updated。
-X:Do not update links,cache isstill rebuilt。