兩種庫
靜態庫動態庫
區別:在於**被載入的時刻不同。靜態庫的**在編譯過程中已經被載入可執行程式,因此體積較大。共享庫的**是在可執行程式執行時才載入記憶體的,在編譯過程中僅簡單的引用,因此**體積較小
庫的儲存位置和命名規範
儲存:一般放在/usr/lib和/lib下
命名規範:
1. 靜態庫的名字一般為lib***x.a,其中***x是該lib的名稱
2. 動態庫的名字一般為lib***x.so.major.minor,***x是該動態庫的名稱,major是主版本號, minor是副版本號
檢視乙個可執行程式依賴哪些庫
ldd命令可以檢視乙個可執行程式依賴的共享庫
在新安裝乙個庫之後如何讓系統能夠找到他標頭檔案so.h
#ifndef so_h
#define so_h
int add(int a, int b);
#endif /*so_h*/
實現檔案so.c
#include "so.h"
int add(int a, int b)
gcc -fpic -c so.c
//生成so.o
gcc -shared -o libtest.so so.o
(上面兩行可以整合成一行:gcc so.c -fpic -shared -o libtest.so
)
注:
-fpic 使輸出的物件模組是按照可重定位位址方式生成的(即與位置無關)。
$ nm -g libtest.so
0000000000000670
t add
0000000000201030 b __bss_start
w __cxa_finalize@@glibc_2.2.5
0000000000201030 d _edata
0000000000201038 b _end
0000000000000684
t _fini
w __gmon_start__
0000000000000540
t _init
w _itm_deregistertmclonetable
w _itm_registertmclonetable
w _jv_registerclasses
#include
#include "so.h"
int main(int argc, char *argv)
使用gcc main.c -l. -ltest -o test
進行編譯。
此時通過readelf test -d
已經能看到生成的可執行檔案test的dynamic section裡依賴libtest.so了
$ readelf test -d
dynamic section at offset 0xe18 contains 25 entries:
tag type name/value
0x0000000000000001 (needed) shared
library: [libtest.so]
0x0000000000000001 (needed) shared
library: [libc.so.6]
......
dynamic symbols中也有乙個undefined symbol(add)
$ nm -d test
u add
0000000000601048 b __bss_start
0000000000601048
d _edata
0000000000601050 b _end
00000000004007b4 t _fini
w __gmon_start__
0000000000400578 t _init
w _itm_deregistertmclonetable
w _itm_registertmclonetable
w _jv_registerclasses
u __libc_start_main
u printf
在執行隱式鏈結的程式之前要注意設定ld_library_path
環境變數,或者把前面生成的libtest.so複製到系統路徑下,否則會找不到動態庫。
$ ./test
./test: error while loading shared libraries: libtest.so: cannot open
shared object file: no such file
or directory
$ export ld_library_path=.
$ ./test
3
顯式鏈結(執行時鏈結)
編寫主程式dyn_main.c
#include
#include
int main(int argc, char *argv)
add = (int(*)(int, int))dlsym(dl, "add");
if( dlerror() != null )
printf("%d\n", add(1, 2));
return
0;}
使用gcc dyn_main.c -ldl -o dyn_test
編譯。
這時通過readelf dyn_test -d
可以發現,dyn_test不依賴libtest.so:
$ readelf dyn_test -d
dynamic section at offset 0xe18 contains 25 entries:
tag type name/value
0x0000000000000001 (needed) shared
library: [libdl.so.2]
0x0000000000000001 (needed) shared
library: [libc.so.6]
......
dyn_test的dynamic symbols中也沒有add:
$ nm -d dyn_test
u dlerror
u dlopen
u dlsym
w __gmon_start__
w _itm_deregistertmclonetable
w _itm_registertmclonetable
w _jv_registerclasses
u __libc_start_main
u printf
u puts
執行程式也不需要設定ld_library_path
環境變數
$ ./dyn_test
3
參考資料
linux下編譯鏈結動態庫
Linux 編譯靜態鏈結庫與動態鏈結庫的方法
hello.c include int main int argc,char argv 1 編譯生成可執行檔案 gcc o test hello.c 2 編譯生成目標檔案 gcc c o test.o hello.c string.c define endstring 0 int strlen ch...
linux 編譯靜態鏈結庫和動態鏈結庫
我們通常把一些公用函式製作成函式庫,供其它程式使用。函式庫分為靜態庫和動態庫兩種。靜態庫在程式編譯時會被連線到目標 中,程式執行時將不再需要該靜態庫。動態庫在程式編譯時並不會被連線到目標 中,而是在程式執行是才被載入,因此在程式執行時還需要動態庫存在。本文主要通過舉例來說明在linux中如何建立靜態...
Linux下動態鏈結庫和靜態鏈結庫
第一部分 編譯過程 預處理過程,負責標頭檔案展開,巨集替換,條件編譯的選擇,刪除注釋等工作。gcc e表示進行預處理。編譯過程,負載將預處理生成的檔案,經過詞法分析,語法分析,語義分析及優化後生成彙編檔案。gcc s表示進行編譯。彙編,是將彙編 轉換為機器可執行指令的過程。通過使用gcc c或者as...