時(shí)間:2015/6/28來源:IT貓撲網(wǎng)作者:網(wǎng)管聯(lián)盟我要評論(0)
一、為什么要使用庫文件
我們在實(shí)際編程工作中肯定會(huì)遇到這種情況:有幾個(gè)項(xiàng)目里有一些函數(shù)模塊的功能相同,
實(shí)現(xiàn)代碼也相同,也是我們所說的重復(fù)代碼。比如,很多項(xiàng)目里都有一個(gè)用戶驗(yàn)證的功能。
代碼段如下:
//UserLogin.h文件,提供函數(shù)聲明
int IsValidUser(char* username, int namelen);
//UserLogin.c文件,實(shí)現(xiàn)對用戶信息的驗(yàn)證
int IsValidUser(char* username, int namelen)
{
int IsValid = 0;
/*下面是具體的處理代碼,略去*/
return IsValid
}
如果每個(gè)項(xiàng)目都保存著這兩個(gè)UserLogin.h和UserLogin.c文件,會(huì)有以下幾個(gè)
弊端:
1、每個(gè)項(xiàng)目里都有重復(fù)的模塊,造成代碼重復(fù)。
2、代碼的重用性不好,一旦IsValidUser的代碼發(fā)生了變化,為了保持設(shè)計(jì)的一致性,
我們還要手工修改其他項(xiàng)目里的UserLogin.c文件,既費(fèi)時(shí)又費(fèi)力,還容易出錯(cuò)。
庫文件就是對公共代碼的一種組織形式。
為了解決上面兩個(gè)弊端,就提出了用庫文件存放公共代碼的解決方案,其要點(diǎn)就是
把公共的(也就是可以被多次復(fù)用的)目標(biāo)代碼從項(xiàng)目中分離出來,統(tǒng)一存放到庫文件中,
項(xiàng)目要用到這些代碼的時(shí)候,在編譯或者運(yùn)行的時(shí)候從庫文件中取得目標(biāo)代碼即可。庫文件
又分兩種:靜態(tài)庫和動(dòng)態(tài)庫。
二、靜態(tài)庫與動(dòng)態(tài)庫
如果程序是在編譯時(shí)加載庫文件的,就是使用了靜態(tài)庫。如果是在運(yùn)行時(shí)加載目標(biāo)代碼,
就成為動(dòng)態(tài)庫。換句話說,如果是使用靜態(tài)庫,則靜態(tài)庫代碼在編譯時(shí)就拷貝到了程序的代碼段,
程序的體積會(huì)膨脹。如果使用動(dòng)態(tài)庫,則程序中只保留庫文件的名字和函數(shù)名,在運(yùn)行時(shí)去查找
庫文件和函數(shù)體,程序的體積基本變化不大。
靜態(tài)庫的原則是"以空間換時(shí)間",增加程序體積,減少運(yùn)行時(shí)間;
動(dòng)態(tài)庫則是"以時(shí)間換空間",增加了運(yùn)行時(shí)間,但減少了程序本身的體積。
下面我們就以實(shí)際例子來看看如何使用這兩種庫.
三、靜態(tài)庫的編寫和使用
1、概述
靜態(tài)庫文件的擴(kuò)展名一般為.a,其編寫步驟很簡單。
、啪帉懞瘮(shù)代碼
、凭幾g生成各目標(biāo)文件
、怯胊r文件對目標(biāo)文件歸檔,生成靜態(tài)庫文件。
注意歸檔文件名必須以lib打頭。
使用要點(diǎn):
、旁趃cc 的-I參數(shù)后加上靜態(tài)庫頭文件的路徑。
、圃趃cc 的-L參數(shù)后加上庫文件所在目錄
、窃趃cc 的-l參數(shù)后加上庫文件名,但是要去掉lib和.a擴(kuò)展名。
比如庫文件名是libtest.a 那么參數(shù)就是 -l test
2、編寫最簡單的靜態(tài)庫文件
編寫如下兩個(gè)文件,注意放在同一目錄中
myalib.h //靜態(tài)庫頭文件
myalib.c //靜態(tài)庫實(shí)現(xiàn)文件
//myalib.h 文件的內(nèi)容
void test();
//myalib.c 文件的內(nèi)容
#inlcude
void test()
{
printf("test\n");
}
3、制作庫文件
、派赡繕(biāo)文件
gcc -c myalib.c
執(zhí)行完后會(huì)生成一個(gè)myalib.o文件
、朴胊r命令歸檔,格式為ar -rc <生成的檔案文件名> <.o文件名列表>
再次提醒,歸檔文件名一定要以lib打頭, .a結(jié)尾。
ar -rc libtest.a myalib.o
執(zhí)行完后會(huì)生成一個(gè)libtest.a文件
4、使用庫文件
、啪帉懸粋(gè)測試程序main.c,內(nèi)容為
//main.c 測試靜態(tài)庫調(diào)用的程序
#include "myalib.h" //要把函數(shù)的頭文件包含進(jìn)來,否則編譯時(shí)會(huì)報(bào)錯(cuò)
int main(int argc,char* argv[])
{
test();
return 0;
}
、凭幾g目標(biāo)文件,注意要把靜態(tài)庫頭文件的路徑加到-I參數(shù)里面
gcc -I /root/exercise -o main.o -c main.c
現(xiàn)在生成了一個(gè)main.o文件
、巧煽蓤(zhí)行文件,注意要把靜態(tài)庫文件的路徑加到-L參數(shù)里面,
把庫文件名(去掉打頭的lib和結(jié)尾的.a)加到-l參數(shù)后面。如下面所示
gcc -o main -L/root/exercise main.o -ltest
此時(shí)就會(huì)生成一個(gè)名為main的可執(zhí)行文件
另外,注意- l參數(shù)好象應(yīng)該加到輸入文件名的后面,否則會(huì)報(bào)錯(cuò)。
比如gcc -o main -L/root/exercise -ltest main.o就會(huì)提示
main.o(.text+0x11): In function `main'':
: undefined reference to `test''
collect2: ld returned 1 exit status
原因我還不清楚:-)
、葓(zhí)行可執(zhí)行文件查看效果
執(zhí)行./main, 輸出
test
說明執(zhí)行成功。
四、動(dòng)態(tài)庫的編寫
1、概述
動(dòng)態(tài)庫一般以.so結(jié)尾,就是shared object的意思.
其基本生成步驟為
、啪帉懞瘮(shù)代碼
⑵編譯生成動(dòng)態(tài)庫文件,要加上 -shared 和 -fpic 選項(xiàng) ,
庫文件名以lib開頭, 以.so 結(jié)尾。
使用方式分為兩種: 隱式調(diào)用和顯示調(diào)用
隱式調(diào)用類似于靜態(tài)庫的使用,但需修改動(dòng)態(tài)鏈接庫的配置文件/etc/ld.so.conf;
顯示調(diào)用則是在主程序里使用dlopen、dlsym、dlerror、dlclose等系統(tǒng)函數(shù)。
具體的調(diào)用方式會(huì)在 "五、動(dòng)態(tài)庫的調(diào)用" 中詳細(xì)說明.
2、編寫最簡單的動(dòng)態(tài)庫文件
為了便于對照, 我們?nèi)匀徊捎渺o態(tài)庫中的文件做例子.
編寫如下兩個(gè)文件,注意放在同一目錄中
myalib.h //靜態(tài)庫頭文件
myalib.c //靜態(tài)庫實(shí)現(xiàn)文件
//myalib.h 文件的內(nèi)容
void test();
//myalib.c 文件的內(nèi)容
#inlcude
void test()
{
printf("test\n");
}
3、編譯生成動(dòng)態(tài)庫 ,庫文件名以lib開頭, 以.so 結(jié)尾。
gcc -fpic -shared -o libtest.so myalib.c
此時(shí)就生成一個(gè)libtest.so文件
五、動(dòng)態(tài)庫的隱式調(diào)用
隱式調(diào)用的含義是代碼里不出現(xiàn)庫文件名,就是說這個(gè)代碼和
調(diào)用靜態(tài)庫的代碼是類似的。
1、編寫測試文件
//main.c 測試動(dòng)態(tài)庫隱式調(diào)用的程序
#include "myalib.h" //要把函數(shù)的頭文件包含進(jìn)來,否則編譯時(shí)會(huì)報(bào)錯(cuò)
int main(int argc,char* argv[])
{
test();
return 0;
}
2、 編譯測試程序,與靜態(tài)庫類似,要把頭文件的路徑加到-I參數(shù)里面
gcc -I /root/exercise -o main.o -c main.c
現(xiàn)在生成了一個(gè)main.o文件
3、連接生成測試程序
gcc -o main -L/root/exercise main.o -ltest
現(xiàn)在生成了一個(gè)main文件
4、執(zhí)行測試程序
./main
此時(shí)出現(xiàn)提示
./main: error while loading shared libraries: libtest.so: cannot open shared object file: No such file or directory。
這個(gè)原因就是程序運(yùn)行時(shí)并不知道動(dòng)態(tài)庫所在的路徑,因此自然找不到。
解決這個(gè)問題的辦法有三種。見下節(jié)
六、使動(dòng)態(tài)庫被系統(tǒng)共享的三種辦法
(再次說明: 本節(jié)參考了計(jì)算機(jī)世界網(wǎng)雨亦奇的文章"LINUX動(dòng)態(tài)鏈接庫高級應(yīng)用"
地址https://www.ccw.com.cn/htm/center/prog/02_3_13_3_2.asp)
(1)拷貝動(dòng)態(tài)鏈接庫到系統(tǒng)共享目錄下,或在系統(tǒng)共享目錄下為該動(dòng)態(tài)鏈接庫
建立連接(硬連接或符號連接均可,常用符號連接).這里說的系統(tǒng)共享目錄,
指的是LINUX動(dòng)態(tài)鏈接庫存放的目錄,包括
/lib,/usr/lib以及/etc/ld.so.conf文件內(nèi)所列的一系列目錄.
#p#副標(biāo)題#e#
實(shí)例:執(zhí)行
# cp libtest.so /lib
# ldconfig
或:
# ln -s `pwd`/libtest.so /lib
# ldconfig
注意pwd前后有兩個(gè)反引號`,其目的是取得pwd命令的輸出,即當(dāng)前目錄.
此時(shí)再執(zhí)行main,即可成功.
(2)將動(dòng)態(tài)鏈接庫所在目錄名追加到動(dòng)態(tài)鏈接庫配置文件/etc/ld.so.conf中.
# pwd >> /etc/ld.so.conf
# ldconfig
此時(shí)再執(zhí)行main,即可成功.
(3)利用動(dòng)態(tài)鏈接庫管理命令ldconfig,強(qiáng)制其搜索指定目錄,并更新緩存文件,便于動(dòng)態(tài)裝入.
# ldconfig `pwd`
此時(shí)再執(zhí)行main,即可成功.
要注意,第三種方法雖然有效,但效果是暫時(shí)的,供程序測試還可以,一旦再度運(yùn)行l(wèi)dconfig,
則緩存文件內(nèi)容可能改變,所需的動(dòng)態(tài)鏈接庫可能不被系統(tǒng)共享了.
而且無論哪種辦法,其實(shí)質(zhì)都是用ldconfig命令把動(dòng)態(tài)庫文件
所在路徑加入到系統(tǒng)庫列表中,(前兩種永久,第三種臨時(shí))
補(bǔ)充:ldconfig命令的作用(見最后說明)
關(guān)鍵詞標(biāo)簽:linux庫文件相關(guān)閱讀
熱門文章 安裝紅帽子RedHat Linux9.0操作系統(tǒng)教程使用screen管理你的遠(yuǎn)程會(huì)話GNU/Linux安裝vmware如何登錄linux vps圖形界面 Linux遠(yuǎn)程桌面連
人氣排行 Linux下獲取CPUID、硬盤序列號與MAC地址linux tc實(shí)現(xiàn)ip流量限制dmidecode命令查看內(nèi)存型號linux下解壓rar文件安裝紅帽子RedHat Linux9.0操作系統(tǒng)教程Ubuntu linux 關(guān)機(jī)、重啟、注銷 命令lcx.exe、nc.exe、sc.exe入侵中的使用方法查看linux服務(wù)器硬盤IO讀寫負(fù)載