靜態庫與動態庫
什么是庫文件?
-
提供變量,函數/類的封裝的代碼倉庫
-
不能單獨運行 而一般的程序文件可以單獨運行
-
分為靜態庫和動態庫
-
好處: 代碼保密 方便部署和分發
動態庫與靜態庫的區別
靜態庫在程序鏈接階段被復制到程序中, 動態庫在程序運行時由系統定位動態庫文件並加載到內存中使用

| 庫類型 | 優點 | 缺點 |
|---|---|---|
| 靜態 | 打包到應用程序中加載速度快 | 消耗系統資源,浪費內存 |
| 發布程序無需提供靜態庫,移植方便 | 更新、部署、發布麻煩 | |
| 動態 | 可以實現進程間資源共享(共享庫) | |
| 更新、部署、發布簡單 | 加載速度比靜態庫慢 運行時需要查找庫再加入 | |
| 可以控制何時加載動態庫 | 發布程序時需要提供依賴的動態庫 |
命名規則
靜態庫
Linux: libxxx.a 只有xxx是自定義
Windows:libxxx.lib xxx自定義
動態庫
Linux:libxxx.so
Windows:libxxx.dll
庫的制作與使用
靜態
r 將文件插入備存文件(備存文件?)
c 建立備存文件索引
s 索引
gcc a.c b.c -o a.o b.o
ar rcs libxxx.a a.o b.o
當前文件
root@iZwz953bcwdl9hfnde2odsZ:~/Linux/lession05/calc# tree
.
├── add.c
├── div.c
├── head.h
├── libcalc.a
├── main.c
├── mult.c
└── sub.c
編譯成目標文件
root@iZwz953bcwdl9hfnde2odsZ:~/Linux/lession05/calc# gcc -c add.c div.c mult.c sub.c
root@iZwz953bcwdl9hfnde2odsZ:~/Linux/lession05/calc# tree
.
├── add.c
├── add.o
├── div.c
├── div.o
├── head.h
├── main.c
├── mult.c
├── mult.o
├── sub.c
└── sub.o
創建靜態庫
root@iZwz953bcwdl9hfnde2odsZ:~/Linux/lession05/calc# ar rcs libcalc.a sub.o div.o mult.o add.o
root@iZwz953bcwdl9hfnde2odsZ:~/Linux/lession05/calc# tree
.
├── add.c
├── add.o
├── div.c
├── div.o
├── head.h
├── libcalc.a
├── main.c
├── mult.c
├── mult.o
├── sub.c
└── sub.o
使用靜態庫
root@iZwz953bcwdl9hfnde2odsZ:~/Linux/lession05/library# tree
.
├── include
│ └── head.h
├── lib
│ └── libcalc.a
├── main.c
└── src
├── add.c
├── div.c
├── mult.c
└── sub.c
編譯main程序頭文件
root@iZwz953bcwdl9hfnde2odsZ:~/Linux/lession05/library# gcc main.c -o app
main.c:2:10: fatal error: head.h: No such file or directory
2 | #include "head.h"
| ^~~~~~~~
compilation terminated.
提供了頭文件 但找不到定義的內部內容
root@iZwz953bcwdl9hfnde2odsZ:~/Linux/lession05/library# gcc main.c -o app -I ./include/
/usr/bin/ld: /tmp/ccmLoZI5.o: in function `main':
main.c:(.text+0x3e): undefined reference to `add'
/usr/bin/ld: main.c:(.text+0x60): undefined reference to `subtract'
/usr/bin/ld: main.c:(.text+0x82): undefined reference to `multiply'
/usr/bin/ld: main.c:(.text+0xa4): undefined reference to `divide'
collect2: error: ld returned 1 exit status
提供靜態庫
root@iZwz953bcwdl9hfnde2odsZ:~/Linux/lession05/library# gcc main.c -o app -I ./include/ -l calc -L ./lib/
執行程序
root@iZwz953bcwdl9hfnde2odsZ:~/Linux/lession05/library# ./app
a = 20, b = 12
a+b= 32
a-b= 8
a*b= 240
a/b= 1.666667
動態
ldd list dynamic dependencies 檢查依賴
定位共享庫文件
知道庫的名字不夠,它會先后搜索elf文件的 DT_RPATH段 ——> 環境變量
LD_LIBRARY_PATH ——> /etc/ld.so.cache文件列表 ——> /lib/,/usr/lib
目錄找到庫文件后將其載入內存
- 使用LD_LIBRARTY_PATH
- 使用/lib/, /usr/lib/
動態庫制作
├── calc
│ ├── add.c
│ ├── div.c
│ ├── head.h
│ ├── main.c
│ ├── mult.c
│ └── sub.c
└── library
├── include
│ └── head.h
├── lib
│ └── libcalc.so
├── main
├── main.c
└── src
├── add.c
├── div.c
├── mult.c
└── sub.c
生成位置無關代碼
root@iZwz953bcwdl9hfnde2odsZ:~/Linux/lession06/calc# gcc -c -fpic add.c div.c mult.c sub.c
root@iZwz953bcwdl9hfnde2odsZ:~/Linux/lession06/calc# tree
.
├── add.c
├── add.o
├── div.c
├── div.o
├── head.h
├── main.c
├── mult.c
├── mult.o
├── sub.c
└── sub.o
生成共享動態庫
root@iZwz953bcwdl9hfnde2odsZ:~/Linux/lession06/calc# gcc -shared *.o -o libcalc.so
root@iZwz953bcwdl9hfnde2odsZ:~/Linux/lession06/calc# tree
.
├── add.c
├── add.o
├── div.c
├── div.o
├── head.h
├── libcalc.so
├── main.c
├── mult.c
├── mult.o
├── sub.c
└── sub.o
使用動態庫
├── include
│ └── head.h
├── lib
│ └── libcalc.so
├── main
├── main.c
└── src
├── add.c
├── div.c
├── mult.c
# gcc main.c -o main -I ./include/ -L ./lib/ -l calc
# ldd main 查看依賴關系
提示無法找到共享庫時
使用以下三種方法 定位動態庫文件 因為動態庫是在最后加入內存
環境變量LD_LIBRARY_PATH
export LD_LIBRARY_PATH = $LD_LIBRARY_PATH : /root/Linux/lession06/library/lib 暫時的環境變量 重啟終端后刪除
root@iZwz953bcwdl9hfnde2odsZ:~/Linux/lession06/library# ldd
ldd: missing file arguments
Try `ldd --help' for more information.
root@iZwz953bcwdl9hfnde2odsZ:~/Linux/lession06/library# ldd main
linux-vdso.so.1 (0x00007ffc1cd4d000)
libcalc.so => /root/Linux/lession06/library/lib/libcalc.so (0x00007f7a5f3bf000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f7a5f1c6000)
/lib64/ld-linux-x86-64.so.2 (0x00007f7a5f3cb000)
vim .bashrc 用戶級別永久環境變量
最后插入export LD_LIBRARY_PATH = $LD_LIBRARY_PATH : /root/Linux/lession06/library/lib
. .bashrc或者source .bashrc
vim /etc/profile 系統級別環境變量
下同上
配置/etc/ld.so.cache文件列表
二進制文件無法直接修改 因此間接
# vim /etc/ld.so.conf
include /etc/ld.so.conf.d/*.conf
/root/Linux/lession06/library/lib 插入的內容
