linux下的共享庫和靜態(tài)庫
(1)linux下文件的類型是不依賴于其后綴名的,但一般來講:
.o,是目標(biāo)文件。
.so 為共享庫,是shared object,用于動(dòng)態(tài)連接的。
.a為靜態(tài)庫,是好多個(gè).o合在一起,用于靜態(tài)連接。
(2)靜態(tài)庫的生成和使用
概述靜態(tài)庫文件的擴(kuò)展名一般為.a,其編寫步驟很簡單。
⑴編寫函數(shù)代碼
⑵編譯生成各目標(biāo)文件
⑶用ar文件對(duì)目標(biāo)文件歸檔,生成靜態(tài)庫文件。
注意歸檔文件名必須以lib打頭。
使用要點(diǎn):
⑴在gcc 的-I參數(shù)后加上靜態(tài)庫頭文件的路徑。
⑵在gcc 的-L參數(shù)后加上庫文件所在目錄
⑶在gcc 的-l參數(shù)后加上庫文件名,但是要去掉lib和.a擴(kuò)展名。比如庫文件名是 libtest.a 那么參數(shù)就是 -l test
細(xì)節(jié):靜態(tài)庫的后綴是.a,它的產(chǎn)生分兩步:
Step 1.由源文件編譯生成一堆.o,每個(gè).o里都包含這個(gè)編譯單元的符號(hào)表。
Step 2.ar命令將很多.o轉(zhuǎn)換成.a,成文靜態(tài)庫。
例如生成靜態(tài)庫 :庫名 libmylib.a
gcc -c mylib.c -o mylib.o
ar rcs libmylib.a mylib.o
將靜態(tài)庫copy到 /usr/lib/ 或/lib/ 目錄下
cp libmylib.a /usr/lib/
靜態(tài)庫的使用
比如測試文件為test.c
gcc -0 test test.c -lmylib
-l為選項(xiàng), mylib為庫名。mylib為libmylib的中間部分,Linux下約定所有庫都以前綴lib開始.在test.c中要包含頭文件。
(3)動(dòng)態(tài)庫的生成和使用
1.生成步驟:
先寫好頭文件和程序文件,如mylib.h和mylib.c。
再編譯下面命令把mylib.c程序創(chuàng)建成了一個(gè)動(dòng)態(tài)庫
(1)、gcc -fPIC -o mylib.o -c mylib.c
(2)、gcc -shared -o libtest.so mylib.o
也可以直接使用一條命令
gcc -fPIC -shared -o libtest.so mylib.c
由以上命令生成動(dòng)態(tài)庫libtest.so,為了不需要?jiǎng)討B(tài)加載動(dòng)態(tài)庫,在命令時(shí)需以lib開頭以.so為后綴。
–fPIC:表示編譯為位置獨(dú)立的代碼,不用此選項(xiàng)的話編譯后的代碼是位置相關(guān)的所以動(dòng)態(tài)載入時(shí)是通過代碼拷貝的方式來滿足不同進(jìn)程的需要,而不能達(dá)到真正代碼段共享的目的。
–shared:指明編譯成動(dòng)態(tài)庫。
-soname name 選項(xiàng),可以指定 soname 是什么。
-o name 指定了共享對(duì)象的 real name。
-Wl選項(xiàng)把參數(shù)傳遞給連接器ld。
-lc選項(xiàng),表示使用c語言庫,一般都要用到。
總結(jié)就是g++/gcc -g -shared -Wl,-soname,lib***.so -o lib***.so.1.0.0 library1.o library2.o .... -lc
2.使用動(dòng)態(tài)庫
在源程序中添加頭文件,假設(shè)原程序名為test.c
編譯命令:gcc test.c –ltest –o test
或者
gcc test.c /usr/lib/libtest.so -o test
這是把libtest.so 復(fù)制到了/usr/lib/,如果沒有復(fù)制到該目錄下就要用–L:指明動(dòng)態(tài)庫所在的目錄。gcc中-l:指明動(dòng)態(tài)庫的名稱,該名稱是處在頭lib和后綴.so中的名稱,如上動(dòng)態(tài)庫libtest.so的l參數(shù)為-l test。
測試:
ldd test
ldd 測試可執(zhí)行文件所使用的動(dòng)態(tài)庫。
注意:引用動(dòng)態(tài)庫時(shí),必須含有路徑,如果只是使用libttt.so,則必須確保這個(gè)庫所在目錄包括再PATH 環(huán)境變量中 。
(4)動(dòng)態(tài)庫的顯式調(diào)用
顯式調(diào)用的含義是代碼出現(xiàn)庫文件名,用戶需要自己去打開和管理庫文件。其要點(diǎn)為:
⑴把dlfcn.h系統(tǒng)頭文件包含進(jìn)來
⑵用dlopen函數(shù)打開庫文件,并指定打開方式:
dllope的的第一個(gè)參數(shù)為共享庫的名稱,將會(huì)在下面位置查找指定的共享庫:
①環(huán)境變量LD_LIBRARY_PATH列出的用分號(hào)間隔的所有目錄。
②文件/etc/ld.so.cache中找到的庫的列表,由ldconfig命令刷新。
③目錄usr/lib。
④目錄/lib。
⑤當(dāng)前目錄。
第二個(gè)參數(shù)為打開共享庫的方式。有兩個(gè)取值
①RTLD_NOW:將共享庫中的所有函數(shù)加載到內(nèi)存
②RTLD_LAZY:會(huì)推后共享庫中的函數(shù)的加載操作,直到調(diào)用dlsym()時(shí)方加載某函數(shù)
⑶用dlerror()函數(shù)測試是否打開成功,并進(jìn)行錯(cuò)誤處理;
⑷用dlsym()獲得函數(shù)地址,存放在一個(gè)函數(shù)指針中
⑸用獲得的函數(shù)指針進(jìn)行函數(shù)調(diào)用。
⑹程序結(jié)束時(shí)用dlclose關(guān)閉打開的動(dòng)態(tài)庫,防止資源泄露。
⑺用ldconfig工具把動(dòng)態(tài)庫的路徑加到系統(tǒng)庫列表中.
---------------------------------------
1.什么是庫在windows平臺(tái)和linux平臺(tái)下都大量存在著庫。
本質(zhì)上來說庫是一種可執(zhí)行代碼的二進(jìn)制形式,可以被操作系統(tǒng)載入內(nèi)存執(zhí)行。
由于windows和linux的本質(zhì)不同,因此二者庫的二進(jìn)制是不兼容的。
本文僅限于介紹linux下的庫。
2.庫的種類
linux下的庫有兩種:靜態(tài)庫和共享庫。
二者的不同點(diǎn)在于代碼被載入的時(shí)刻不同。
靜態(tài)庫的代碼在編譯過程中已經(jīng)被載入可執(zhí)行程序,因此體積較大。
共享庫的代碼是在可執(zhí)行程序運(yùn)行時(shí)才載入內(nèi)存的,在編譯過程中僅簡單的引用,因此代碼體積較小。
3.庫存在的意義
庫是別人寫好的現(xiàn)有的,成熟的,可以復(fù)用的代碼,你可以使用但要記得遵守許可協(xié)議。
現(xiàn)實(shí)中每個(gè)程序都要依賴很多基礎(chǔ)的底層庫,不可能每個(gè)人的代碼都從零開始,因此庫的存在意義非同尋常。
共享庫的好處是,不同的應(yīng)用程序如果調(diào)用相同的庫,那么在內(nèi)存里只需要有一份該共享庫的實(shí)例。
4.庫文件是如何產(chǎn)生的在linux下
靜態(tài)庫的后綴是.a,它的產(chǎn)生分兩步
Step 1.由源文件編譯生成一堆.o,每個(gè).o里都包含這個(gè)編譯單元的符號(hào)表
Step 2.ar命令將很多.o轉(zhuǎn)換成.a,成文靜態(tài)庫
動(dòng)態(tài)庫的后綴是.so,它由gcc加特定參數(shù)編譯產(chǎn)生。
例如:
$ gcc -fPIC -c *.c $ gcc -shared -Wl,-soname, libfoo.so.1 -o libfoo.so.1.0 *.
5.庫文件是如何命名的,有沒有什么規(guī)范
在linux下,庫文件一般放在/usr/lib /lib下,
靜態(tài)庫的名字一般為libxxxx.a,其中xxxx是該lib的名稱
動(dòng)態(tài)庫的名字一般為libxxxx.so.major.minor,xxxx是該lib的名稱,major是主版本號(hào), minor是副版本號(hào)
6.如何知道一個(gè)可執(zhí)行程序依賴哪些庫
ldd命令可以查看一個(gè)可執(zhí)行程序依賴的共享庫,
例如# ldd /bin/lnlibc.so.6
=> /lib/libc.so.6 (0×40021000)/lib/ld-linux.so.2
=> /lib/ld- linux.so.2 (0×40000000)
可以看到ln命令依賴于libc庫和ld-linux庫
7.可執(zhí)行程序在執(zhí)行的時(shí)候如何定位共享庫文件
當(dāng)系統(tǒng)加載可執(zhí)行代碼時(shí)候,能夠知道其所依賴的庫的名字,但是還需要知道絕對(duì)路徑
此時(shí)就需要系統(tǒng)動(dòng)態(tài)載入器(dynamic linker/loader)
對(duì)于elf格式的可執(zhí)行程序,是由ld-linux.so*來完成的,它先后搜索
elf文件的 DT_RPATH段—環(huán)境變量LD_LIBRARY_PATH—/etc/ld.so.cache文件列表—/lib/,/usr/lib目錄
找到庫文件后將其載入內(nèi)存
8.在新安裝一個(gè)庫之后如何讓系統(tǒng)能夠找到他
如果安裝在/lib或者/usr/lib下,那么ld默認(rèn)能夠找到,無需其他操作。
如果安裝在其他目錄,需要將其添加到/etc/ld.so.cache文件中,步驟如下
1.編輯/etc/ld.so.conf文件,加入庫文件所在目錄的路徑
2.運(yùn)行l(wèi)dconfig,該命令會(huì)重建/etc/ld.so.cache文件