|
由于動(dòng)態(tài)鏈接庫(kù)函數(shù)的共享特性,它們不會(huì)被拷貝到可執(zhí)行文件中。在編譯的時(shí)候,編譯器只會(huì)做一些函數(shù)名之類的檢查。在程序運(yùn)行的時(shí)候,被調(diào)用的動(dòng)態(tài)鏈接庫(kù)函數(shù)被安置在內(nèi)存的某個(gè)地方,所有調(diào)用它的程序?qū)⒅赶蜻@個(gè)代碼段。因此,這些代碼必須實(shí)用相對(duì)地址,而不是絕對(duì)地址。在編譯的時(shí)候,我們需要告訴編譯器,這些對(duì)象文件是用來做動(dòng)態(tài)鏈接庫(kù)的,所以要用地址不無關(guān)代碼(Position Independent Code (PIC))。
對(duì)gcc編譯器,只需添加上 -fPIC 標(biāo)簽,如:
gcc -fPIC -c file1.c
gcc -fPIC -c file2.c
gcc –shared -o libxxx.so file1.o file2.o
注意到最后一行,-shared 標(biāo)簽告訴編譯器這是要建立動(dòng)態(tài)鏈接庫(kù)。這與靜態(tài)鏈接庫(kù)的建立很不一樣,后者用的是 ar 命令。也注意到,動(dòng)態(tài)鏈接庫(kù)的名字形式為 “l(fā)ibxxx.so” 后綴名為 “.so”
四、動(dòng)態(tài)鏈接庫(kù)的使用
使用動(dòng)態(tài)鏈接庫(kù),首先需要在編譯期間讓編譯器檢查一些語法與定義。
這與靜態(tài)庫(kù)的實(shí)用基本一樣,用的是 -Lpath 和 -lxxx 標(biāo)簽。如:
gcc file1.o file2.o -Lpath -lxxx -o program.exe
編譯器會(huì)先在path文件夾下搜索libxxx.so文件,如果沒有找到,繼續(xù)搜索libxxx.a(靜態(tài)庫(kù))。
選項(xiàng)的意義:
-shared 該選項(xiàng)指定生成動(dòng)態(tài)連接庫(kù)(讓連接器生成T類型的導(dǎo)出符號(hào)表,有時(shí)候也生成弱連接W類型的導(dǎo)出符號(hào)),不用該標(biāo)志外部程序無法連接。相當(dāng)于一個(gè)可執(zhí)行文件
l -fPIC:表示編譯為位置獨(dú)立的代碼,不用此選項(xiàng)的話編譯后的代碼是位置相關(guān)的所以動(dòng)態(tài)載入時(shí)是通過代碼拷貝的方式來滿足不同進(jìn)程的需要,而不能達(dá)到真正代碼段共享的目的。
l -L.:表示要連接的庫(kù)在當(dāng)前目錄中
l -ltest:編譯器查找動(dòng)態(tài)連接庫(kù)時(shí)有隱含的命名規(guī)則,即在給出的名字前面加上lib,后面加上.so來確定庫(kù)的名稱
l LD_LIBRARY_PATH:這個(gè)環(huán)境變量指示動(dòng)態(tài)連接器可以裝載動(dòng)態(tài)庫(kù)的路徑。
鏈接方法I,拷貝到系統(tǒng)庫(kù)里再鏈接,讓gcc自己查找
$ sudo cp lib***.so /usr/lib
鏈接方法II,手動(dòng)指定庫(kù)路徑
gcc file1.o file2.o -Lpath -lxxx -o program.exe
鏈接方法III,修改環(huán)境變量
$ export LD_LIBRARY_PATH=/path/to/lib
$ ldd test
執(zhí)行test,可以看到它是如何調(diào)用動(dòng)態(tài)庫(kù)中的函數(shù)的。
Ldd:判斷某個(gè)可執(zhí)行的 binary 檔案里有什么動(dòng)態(tài)函式庫(kù):
比靜態(tài)鏈接的程序多了一個(gè) lib***.so ?恩,這就是靜態(tài)與動(dòng)態(tài)的最大區(qū)別,靜態(tài)情況下,他把庫(kù)直接加載到程序里,而在動(dòng)態(tài)鏈接的時(shí)候,他只是保留接口,將動(dòng)態(tài)庫(kù)與程序代碼獨(dú)立。這樣就可以提高代碼的可復(fù)用度,和降低程序的耦合度。
ldconfig和etc/ld.so.conf:將動(dòng)態(tài)凼式庫(kù)加載高速緩存當(dāng)中:
首先,我們必須要在 /etc/ld.so.conf 里面寫下『 想要讀入高速緩存當(dāng)中的動(dòng)態(tài)凼式庫(kù)所在的目錄』,接下來則是利用 ldconfig 這個(gè)執(zhí)行檔將 /etc/ld.so.conf 的資料讀入快取當(dāng)中;
當(dāng)執(zhí)行函數(shù)動(dòng)態(tài)鏈接.so時(shí),如果此文件不在缺省目錄下‘/usr/local/lib’ and ‘/usr/lib’. 那么就需要指定環(huán)境變量LD_LIBRARY_PATH:該環(huán)境變量主要用于指定查找動(dòng)態(tài)鏈接庫(kù)時(shí)除了默認(rèn)路徑之外的其他路徑。(該路徑在默認(rèn)路徑之前查找)
假如現(xiàn)在需要在已有的環(huán)境變量上添加新的路徑名,則采用如下方式
LD_LIBRARY_PATH=NEWDIRS:$LD_LIBRARY_PATH.(newdirs是新的路徑串)
在linux終端下輸入:
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/opt/au1200_rm/build_tools/bin
然后再輸入:export,即會(huì)顯示是否設(shè)置正確
多個(gè)路徑之間用冒號(hào)分隔;例如:
# export LD_LIBRARY_PATH="/usr/lib/old:/opt/lib"
而PATH是執(zhí)行文件路徑的變量
PATH=${PATH}:add_yours
export PATH=${PATH}:add_yours
|
|