天天看點

Linux中庫的生成和使用1    庫的生成和使用

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。

繼續閱讀