天天看點

linux下庫檔案的程式設計

  程式設計到了一定的時候,總喜歡追求新的東西。将代碼盡量子產品化就是我的追求之一,原來隻是滿足于将代碼從單檔案中分離,通過頭檔案和實作檔案實作子產品化,後來發現最好的方法是打包成庫檔案,使用更加友善。盡管在linux和windows下都有大量的庫檔案,由于二者的工具不同,加上筆者主要是在linux下程式設計和教學,是以本文主要介紹Linux下的庫檔案的制作。

  庫檔案在linux中主要有兩種:靜态庫和動态庫(共享庫),二者的不同主要有:

  1、載入時機不同:靜态庫是在編譯時進行載入到代碼中;共享庫在運作時載入到代碼中;

  2、對生成的可執行檔案的影響不同:靜态庫的缺失不會影響後期可執行檔案的運作;共享庫的缺失會影響可執行檔案的執行;

  3、對可執行檔案大小改變不同:靜态庫在編譯過程中将所有檔案添加到可執行檔案中,生成可執行檔案偏大;共享庫在編譯過程中将所有檔案連結到可執行檔案中,生成的可執行檔案幾乎沒有增大;

  4、後期維護的影響不同:靜态庫可能會重複應用,浪費空間;共享庫更容易引用使用,隻需要一份庫實作多個檔案的共享使用;

  5、字尾名稱不同:靜态庫的字尾名是.a; 動态庫的字尾名是.so;

  6、生成方式不同:靜态庫主要是gcc将*.c檔案形成*.o檔案,使用ar指令打包成.a檔案即可;動态庫檔案主要由gcc加上特定參數編譯生成

  7、形成的可執行檔案的執行方式不同:靜态庫生成的可執行檔案直接執行即可;動态庫生成的可執行檔案執行時須保證動态庫檔案能夠被找到:可以将動态庫檔案連結或複制到/usr/lib或/lib目錄,一般不這樣做;設定環境變量LD_LIBRARY_PATH,使用指令export  LD_LIBRARY_PATH=$(pwd);使用指令ldconfig目錄,将制定目錄下的動态連結庫被系統共享起來sudo ldconfig /home/munication/WORKM/libDemo/;

  作為現成的庫檔案,一般都具有成熟可靠、能夠複用、接口明确等特點。是以,善于利用庫檔案,會讓初學者很容易站在巨人的肩膀上。

  下面為了更好的說明問題,通過三種方式來形成一個可執行檔案testCal,功能很簡單。

  一、不是用庫的方式,代碼add.c、sub.c、mul.c、div.c、mod.c、cal.h testCal.c都是一樣的:

add.c  

sub.c

mul.c

div.c

mod.c

cal.h

testCal.c

  這個是附加的檔案makefile,檔案名稱為makefile

  如果有上邊的makefile檔案,下面的操作都是假設上邊所有的檔案:add.c  cal.h  div.c  makefile  mod.c  mul.c  sub.c  testCal.c都在/home/munication/WORKM/libDemo/目錄下

  終端下到/home/munication/WORKM/libDemo/目錄下,

  使用下面的目錄生成可執行檔案,并有下面的提示資訊: 

  如果其中的檔案更改,可以使用同一個指令make即可重新編譯生成新的執行檔案,make會自動判斷那些檔案需要編譯,如果需要把中間檔案删除,使用指令make clean,提示資訊為;

  如果不用makefile檔案,可以使用手工指令:

  檢視檔案大小:

  很明顯,可以看出形成的可執行檔案的大小是7388位元組,7k位元組的大小。

  執行可執行檔案,使用指令:

  二、使用靜态庫檔案,生成靜态庫。庫檔案一般以lib為字首,緊接着是庫的名稱,擴充名為.a,例如我們這裡要建立庫名libcal.a的庫,使用指令ar,具體如下:

  使用靜态庫,建立庫檔案的接口檔案頭檔案,本文中是cal.h檔案,使用庫檔案的檔案testCal.c包含頭檔案cal.h檔案即可,使用如下指令編譯:

  其中上邊指令的說明:

  (1)、gcc -o testCal:使用gcc編譯,-o指定檔案名,後邊的testCal就是最終生成的檔案名

  (2)、-static:指明使用靜态庫

  (3)、-L.:-L指明使用庫,後面的.表明庫檔案在目前目錄

  (4)、-lcal:表明是庫檔案的名稱,其中-表明是選項,l是lib的簡寫,後邊的cal才是真正的庫檔案名稱,字尾名是不需要的

  檢視檔案的大小:

  可以很明顯看出:使用靜态庫檔案的可執行檔案的大小為740140位元組,超過700k位元組

  三、使用動态庫檔案:生成動态庫檔案。庫檔案一般以lib為字首,緊接着是庫的名稱,擴充名為.so,例如我們這裡要建立庫名libcal.so的庫,具體如下: 

  以上,先運作make指令,通過makefile檔案生成目标檔案testCal.o add.o sub.o mul.o div.o mod.o,接着使用下面指令:

  (1)、gcc -o libcal.so:使用gcc編譯,-o指定檔案名,後邊的libcal.so就是最終生成的動态庫名

  (2)、-shared:指明生成動态庫

  (3)、-fPIC.:該選項告訴gcc産生的代碼不要包含對函數和變量具體記憶體位置的引用,運作時進行位址連結

  (1)、gcc -o testCal:使用gcc編譯,-o指定檔案名,後邊的libcal.so就是最終生成可執行檔案名稱

  (2)、沒有使用-static:指明使用動态庫

  可以很明顯看出:使用動态庫檔案的可執行檔案的大小為7296位元組,超過7k位元組,比不打包成庫大了一點,多了連結資訊,比靜态庫小了很多,差不多隻有靜态庫的1%大小。

  執行可執行檔案時,可能會出現錯誤,提示找不到動态庫檔案libcal.so檔案,解決方案主要有如下幾種:

  (1)、将生成的庫檔案libcal.so檔案複制到目錄/usr/lib或者/lib目錄中,這種方式容易污染系統的庫檔案,也可以将自己作的庫檔案libcal.so連結到/usr/lib或/lib中,再次執行可執行檔案就正常了;

  (2)、連接配接器會搜尋LD_LIBRARY_PATH指定的目錄,将該環境變量設定為目前目錄,具體指令為:

  (3)、使用指令ldconfig目錄,将制定目錄下的動态連結庫被系統共享起來,具體指令為:

   最後的附加:可以使用指令ldd檢視可執行檔案執行時調用的動态庫,具體指令為:

  gcc編譯時搜尋庫檔案的順序,可以通過一定的手段覆寫系統的庫檔案,一般不要這麼做,後果可能會很嚴重。

  靜态庫連結時搜尋路徑順序:

  (1). ld 會去找 GCC 指令中的參數-L

  (2). 再找 gcc 的環境變量 LIBRARY_PATH

  (3). 再找内定目錄 /lib /usr/lib /usr/local/lib 這是當初 compile gcc 時寫在程式内的

  動态連結時、執行時搜尋路徑順序:

  (1). 編譯目标代碼時指定的動态庫搜尋路徑;

  (2). 環境變量 LD_LIBRARY_PATH 指定的動态庫搜尋路徑;

  (3). 配置檔案/etc/ld.so.conf 中指定的動态庫搜尋路徑;

  (4). 預設的動态庫搜尋路徑/lib;

  (5). 預設的動态庫搜尋路徑/usr/lib。

  有關環境變量:

  (1).LIBRARY_PATH 環境變量:指定程式靜态連結庫檔案搜尋路徑

  (2).LD_LIBRARY_PATH 環境變量:指定程式動态連結庫檔案搜尋路徑

  

人就像是被蒙着眼推磨的驢子,生活就像一條鞭子;當鞭子抽到你背上時,你就隻能一直往前走,雖然連你也不知道要走到什麼時候為止,便一直這麼堅持着。