IT貓撲網(wǎng):您身邊最放心的安全下載站! 最新更新|軟件分類|軟件專題|手機版|論壇轉(zhuǎn)貼|軟件發(fā)布

您當前所在位置: 首頁操作系統(tǒng)LINUX → linux庫文件的制作

linux庫文件的制作

時間:2015-06-28 00:00:00 來源:IT貓撲網(wǎng) 作者:網(wǎng)管聯(lián)盟 我要評論(0)

  一、為什么要使用庫文件

  我們在實際編程工作中肯定會遇到這種情況:有幾個項目里有一些函數(shù)模塊的功能相同,

  實現(xiàn)代碼也相同,也是我們所說的重復代碼。比如,很多項目里都有一個用戶驗證的功能。

  代碼段如下:

  //UserLogin.h文件,提供函數(shù)聲明

  int IsValidUser(char* username, int namelen);

  //UserLogin.c文件,實現(xiàn)對用戶信息的驗證

  int IsValidUser(char* username, int namelen)

  {

  int IsValid = 0;

  /*下面是具體的處理代碼,略去*/

  return IsValid

  }

  如果每個項目都保存著這兩個UserLogin.h和UserLogin.c文件,會有以下幾個

  弊端:

  1、每個項目里都有重復的模塊,造成代碼重復。

  2、代碼的重用性不好,一旦IsValidUser的代碼發(fā)生了變化,為了保持設計的一致性,

  我們還要手工修改其他項目里的UserLogin.c文件,既費時又費力,還容易出錯。

  庫文件就是對公共代碼的一種組織形式。

  為了解決上面兩個弊端,就提出了用庫文件存放公共代碼的解決方案,其要點就是

  把公共的(也就是可以被多次復用的)目標代碼從項目中分離出來,統(tǒng)一存放到庫文件中,

  項目要用到這些代碼的時候,在編譯或者運行的時候從庫文件中取得目標代碼即可。庫文件

  又分兩種:靜態(tài)庫和動態(tài)庫。

  二、靜態(tài)庫與動態(tài)庫

  如果程序是在編譯時加載庫文件的,就是使用了靜態(tài)庫。如果是在運行時加載目標代碼,

  就成為動態(tài)庫。換句話說,如果是使用靜態(tài)庫,則靜態(tài)庫代碼在編譯時就拷貝到了程序的代碼段,

  程序的體積會膨脹。如果使用動態(tài)庫,則程序中只保留庫文件的名字和函數(shù)名,在運行時去查找

  庫文件和函數(shù)體,程序的體積基本變化不大。

  靜態(tài)庫的原則是"以空間換時間",增加程序體積,減少運行時間;

  動態(tài)庫則是"以時間換空間",增加了運行時間,但減少了程序本身的體積。

  下面我們就以實際例子來看看如何使用這兩種庫.

  三、靜態(tài)庫的編寫和使用

  1、概述

  靜態(tài)庫文件的擴展名一般為.a,其編寫步驟很簡單。

 ?、啪帉懞瘮?shù)代碼

  ⑵編譯生成各目標文件

 ?、怯胊r文件對目標文件歸檔,生成靜態(tài)庫文件。

  注意歸檔文件名必須以lib打頭。

  使用要點:

 ?、旁趃cc 的-I參數(shù)后加上靜態(tài)庫頭文件的路徑。

 ?、圃趃cc 的-L參數(shù)后加上庫文件所在目錄

  ⑶在gcc 的-l參數(shù)后加上庫文件名,但是要去掉lib和.a擴展名。

  比如庫文件名是libtest.a 那么參數(shù)就是 -l test

  2、編寫最簡單的靜態(tài)庫文件

  編寫如下兩個文件,注意放在同一目錄中

  myalib.h?? //靜態(tài)庫頭文件

  myalib.c?? //靜態(tài)庫實現(xiàn)文件

  //myalib.h 文件的內(nèi)容

  void test();

  //myalib.c 文件的內(nèi)容

  #inlcude

  void test()

  {

  printf("test\n");

  }

  3、制作庫文件

 ?、派赡繕宋募?/p>

  gcc -c myalib.c

  執(zhí)行完后會生成一個myalib.o文件

  ⑵用ar命令歸檔,格式為ar -rc <生成的檔案文件名> <.o文件名列表>

  再次提醒,歸檔文件名一定要以lib打頭, .a結(jié)尾。

  ar -rc libtest.a myalib.o

  執(zhí)行完后會生成一個libtest.a文件

  4、使用庫文件

  ⑴編寫一個測試程序main.c,內(nèi)容為

  //main.c 測試靜態(tài)庫調(diào)用的程序

  #include "myalib.h"?? //要把函數(shù)的頭文件包含進來,否則編譯時會報錯

  int main(int argc,char* argv[])

  {

  test();

  return 0;

  }

 ?、凭幾g目標文件,注意要把靜態(tài)庫頭文件的路徑加到-I參數(shù)里面

  gcc -I /root/exercise -o main.o -c main.c

  現(xiàn)在生成了一個main.o文件

  ⑶生成可執(zhí)行文件,注意要把靜態(tài)庫文件的路徑加到-L參數(shù)里面,

  把庫文件名(去掉打頭的lib和結(jié)尾的.a)加到-l參數(shù)后面。如下面所示

  gcc -o main -L/root/exercise?? main.o -ltest

  此時就會生成一個名為main的可執(zhí)行文件

  另外,注意- l參數(shù)好象應該加到輸入文件名的后面,否則會報錯。

  比如gcc -o main -L/root/exercise?? -ltest main.o就會提示

  main.o(.text+0x11): In function `main'':

  : undefined reference to `test''

  collect2: ld returned 1 exit status

  原因我還不清楚:-)

 ?、葓?zhí)行可執(zhí)行文件查看效果

  執(zhí)行./main, 輸出

  test

  說明執(zhí)行成功。

  四、動態(tài)庫的編寫

  1、概述

  動態(tài)庫一般以.so結(jié)尾,就是shared object的意思.

  其基本生成步驟為

 ?、啪帉懞瘮?shù)代碼

 ?、凭幾g生成動態(tài)庫文件,要加上 -shared 和 -fpic 選項 ,

  庫文件名以lib開頭, 以.so 結(jié)尾。

  使用方式分為兩種: 隱式調(diào)用和顯示調(diào)用

  隱式調(diào)用類似于靜態(tài)庫的使用,但需修改動態(tài)鏈接庫的配置文件/etc/ld.so.conf;

  顯示調(diào)用則是在主程序里使用dlopen、dlsym、dlerror、dlclose等系統(tǒng)函數(shù)。

  具體的調(diào)用方式會在 "五、動態(tài)庫的調(diào)用" 中詳細說明.

  2、編寫最簡單的動態(tài)庫文件

  為了便于對照, 我們?nèi)匀徊捎渺o態(tài)庫中的文件做例子.

  編寫如下兩個文件,注意放在同一目錄中

  myalib.h?? //靜態(tài)庫頭文件

  myalib.c?? //靜態(tài)庫實現(xiàn)文件

  //myalib.h 文件的內(nèi)容

  void test();

  //myalib.c 文件的內(nèi)容

  #inlcude

  void test()

  {

  printf("test\n");

  }

  3、編譯生成動態(tài)庫 ,庫文件名以lib開頭, 以.so 結(jié)尾。

  gcc -fpic -shared -o libtest.so myalib.c

  此時就生成一個libtest.so文件

  五、動態(tài)庫的隱式調(diào)用

  隱式調(diào)用的含義是代碼里不出現(xiàn)庫文件名,就是說這個代碼和

  調(diào)用靜態(tài)庫的代碼是類似的。

  1、編寫測試文件

  //main.c 測試動態(tài)庫隱式調(diào)用的程序

  #include "myalib.h"?? //要把函數(shù)的頭文件包含進來,否則編譯時會報錯

  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)在生成了一個main.o文件

  3、連接生成測試程序

  gcc -o main -L/root/exercise?? main.o -ltest

  現(xiàn)在生成了一個main文件

  4、執(zhí)行測試程序

  ./main

  此時出現(xiàn)提示

  ./main: error while loading shared libraries: libtest.so: cannot open shared object file: No such file or directory。

  這個原因就是程序運行時并不知道動態(tài)庫所在的路徑,因此自然找不到。

  解決這個問題的辦法有三種。見下節(jié)

  六、使動態(tài)庫被系統(tǒng)共享的三種辦法

  (再次說明: 本節(jié)參考了計算機世界網(wǎng)雨亦奇的文章"LINUX動態(tài)鏈接庫高級應用"

  地址http://www.ccw.com.cn/htm/center/prog/02_3_13_3_2.asp)

  (1)拷貝動態(tài)鏈接庫到系統(tǒng)共享目錄下,或在系統(tǒng)共享目錄下為該動態(tài)鏈接庫

  建立連接(硬連接或符號連接均可,常用符號連接).這里說的系統(tǒng)共享目錄,

  指的是LINUX動態(tài)鏈接庫存放的目錄,包括

  /lib,/usr/lib以及/etc/ld.so.conf文件內(nèi)所列的一系列目錄.

#p#副標題#e#

  實例:執(zhí)行

  # cp libtest.so /lib

  # ldconfig

  或:

  # ln -s `pwd`/libtest.so /lib

  # ldconfig

  注意pwd前后有兩個反引號`,其目的是取得pwd命令的輸出,即當前目錄.

  此時再執(zhí)行main,即可成功.

  (2)將動態(tài)鏈接庫所在目錄名追加到動態(tài)鏈接庫配置文件/etc/ld.so.conf中.

  # pwd >> /etc/ld.so.conf

  # ldconfig

  此時再執(zhí)行main,即可成功.

  (3)利用動態(tài)鏈接庫管理命令ldconfig,強制其搜索指定目錄,并更新緩存文件,便于動態(tài)裝入.

  # ldconfig `pwd`

  此時再執(zhí)行main,即可成功.

  要注意,第三種方法雖然有效,但效果是暫時的,供程序測試還可以,一旦再度運行l(wèi)dconfig,

  則緩存文件內(nèi)容可能改變,所需的動態(tài)鏈接庫可能不被系統(tǒng)共享了.

  而且無論哪種辦法,其實質(zhì)都是用ldconfig命令把動態(tài)庫文件

  所在路徑加入到系統(tǒng)庫列表中,(前兩種永久,第三種臨時)

  補充:ldconfig命令的作用(見最后說明)

關鍵詞標簽:linux庫文件

相關閱讀

文章評論
發(fā)表評論

熱門文章 安裝紅帽子RedHat Linux9.0操作系統(tǒng)教程 安裝紅帽子RedHat Linux9.0操作系統(tǒng)教程 Tomcat9.0如何安裝_Tomcat9.0環(huán)境變量配置方法 Tomcat9.0如何安裝_Tomcat9.0環(huán)境變量配置方法 多種操作系統(tǒng)NTP客戶端配置 多種操作系統(tǒng)NTP客戶端配置 Linux操作系統(tǒng)修改IP Linux操作系統(tǒng)修改IP

相關下載

    人氣排行 Linux下獲取CPUID、硬盤序列號與MAC地址 dmidecode命令查看內(nèi)存型號 linux tc實現(xiàn)ip流量限制 安裝紅帽子RedHat Linux9.0操作系統(tǒng)教程 linux下解壓rar文件 lcx.exe、nc.exe、sc.exe入侵中的使用方法 Ubuntu linux 關機、重啟、注銷 命令 查看linux服務器硬盤IO讀寫負載