[註:本文中的操作在ubuntu-10.04.4上進行。]
靜態庫與動態庫
從本質上來說,庫是一種可執行代碼的二進位形式,可以被作業系統載入記憶體執行,無論靜態庫還是動態庫,都是由.o檔案(目標檔案)建立的。
- 靜態庫:靜態庫的代碼在編譯過程中已經被載入可執行程式,因此程式體積較大。
- 動態庫:不同的應用程式如果調用相同的庫,那麼在記憶體裡只需要一份該動態庫。單獨的動態庫升級更換不影響其他動態庫的正常載入使用,便於升級。
編譯多個源檔案
1. 建立hello.c:
#include<stdio.h>void hello(){ printf(“Hello world!\n”);}
執行命令gcc –c hello.c,產生目標檔案hello.o。
2. 建立hello.h:
#ifndef _HELLO_#define _HELLO_extern voidhello();#endif //_HELLO_
3. 建立main.c:
#include “hello.h”int main(intargc, char **argv){ hello(); return 0;}
4. 執行命令gcc –c main產生目標檔案main.o
5. 將hello.o和main.o聯合編譯產生可執行檔hello:gcc –o hello hello.o main.o
註:多檔案編譯產生可執行檔hello的大小為7184B。
靜態庫的產生與引用
1. 執行命令gcc –c hello.c,產生目標檔案hello.o;
2. 執行命令ar rcs libhello.a hello.o,產生靜態庫檔案libhello.a;
3. 編譯時間載入靜態檔案gcc –o hello main.c –static –L. –lhello,產生可執行檔hello。
註:靜態庫產生的可執行檔hello的大小為594740B,靜態庫libhello.a的大小為982B,刪除靜態庫後,hello依然可以執行。可以看出載入靜態庫的可執行檔比較大。
動態庫的產生與引用
1. 執行命令gcc –c hello.c,產生目標檔案hello.o;
2. 執行命令gcc –shared –fPIC –o libhello.so hello.o,產生動態庫libhello.so;
3. 執行命令gcc –o hello main.c –L. –lhello,產生可執行檔hello。
此時運行hello:$./hello將報錯:
./hello: errorwhile loading shared libraries: libhello.so: cannot open shared object file: Nosuch file or director
4. 想要執行hello,需要連結到動態庫,方法如下:
a) 將libhello.so拷貝到目錄/usr/lib中;
b) export LD_LIBRARY_PATH=$(pwd),將libhello.so所在目錄(目前的目錄)加入到LD_LIBRARY_PATH;
c) chcon –t texrel_shlib_t/usr/lib/libhello.so,分享庫的絕對路徑;[?此命令作用未明]
註:引用動態庫的可執行檔hello大小為7128B,動態庫libhello.so的大小為6734B,相比編譯多個源檔案產生hello大小7184B,可以看出載入動態庫不會導致可執行檔變大。為確保hello可以成功執行,必須保證應用程式能夠連結到動態庫,經驗證:只要4.a)或者4.b)有一項完成就行。
連結器如何載入動態庫
連結器搜尋動態庫的順序:
1. elf檔案的DT_RPATH段;
2. 環境變數LD_LIBRARY_PATH;
3. /etc/ld.so.cache檔案清單;
4. /lib, /usr/lib目錄;
只要找到動態庫,就將其載入記憶體。