linux动态链接库
前言
靜態鏈接庫會編譯進可執行文件,并被加載到內存,會造成空間浪費
靜態鏈接庫對程序的更新、部署、發布帶來麻煩。如果靜態庫更新了,使用它的應用程序都需要重新編譯、發布給用戶(對于玩家來說,可能是一個很小的改動,卻導致整個程序重新下載,全量更新)
動態庫在程序編譯時并不會被鏈接到目標代碼中,而是在執行文件中記錄對動態庫的引用,在程序運行時才被載入。不同的應用程序如果調用相同的庫,那么在內存里只需要有一份該共享庫的實例,規避了空間浪費問題。動態庫在程序運行時才被載入,也解決了靜態庫對程序的更新、部署和發布帶來的麻煩,用戶只需要更新動態庫即可,增量更新。
Linux下動態庫文件的文件名形如 libxxx.so,其中so是 Shared Object 的縮寫,即可以共享的目標文件。
特點
- 動態庫把對一些庫函數的鏈接載入推遲到程序運行的時期
- 可以實現進程之間的資源共享。(因此動態庫也稱為共享庫)
- 將一些程序升級變得簡單。
- 甚至可以真正做到鏈接載入完全由程序員在程序代碼中控制(顯示調用)
生成動態鏈接庫
例子
源文件
add.c
int add(int a, int b) {return a + b; }subtract.c
int subtract(int a, int b) {return a - b; }編譯
gcc -fPIC -c add.c gcc -fPIC -c subtract.c其中,PIC是 Position Independent Code 的縮寫,表示要生成位置無關的代碼,這是動態庫需要的特性
鏈接
gcc -shared -o libmymath.so subtract.o add.o-shared是鏈接選項,告訴gcc生成動態庫而不是可執行文件
這兩步可以合并成一個命令:
gcc -o libmymath.so -fPIC -shared subtract.c add.c編寫頭文件
#ifndef _MYMATH_H_ #define _MYMATH_H_int add(int, int); int subtract(int, int);#endif使用鏈接庫
main.c
#include <stdio.h> #include "mymath.h"int main() {printf("%d, %d\n", add(2, 3), subtract(9, 8));return 0; }鏈接
gcc main.c -L. -lmymath如果同一目錄下同時存在同名的動態庫和靜態庫,比如 libmymath.so 和 libmymath.a 都在當前路徑下,則gcc會優先鏈接動態庫。
運行
當執行 ./a.out,發現程序報錯
./a.out: error while loading shared libraries: libmymath.so: cannot open shared object file: No such file or directory這涉及到程序如何定位共享庫文件
/etc/ld.so.cache 是 ldconfig 程序讀取 /etc/ld.so.conf 文件生成的
所以,我們想讓程序找到自己寫的動態鏈接庫,有如下方法:
- 指定 LD_LIBRARY_PATH 環境變量為 libmymath.so 文件所在的目錄
- 編輯/etc/ld.so.conf文件,加入庫文件所在目錄的路徑; 同時,運行ldconfig ,該命令會重建/etc/ld.so.cache文件
- 把 libmymath.so 拷貝到/lib或者/usr/lib下,那么ld默認能夠找到,無需其他操作
我們可以執行:
?
LD_LIBRARY_PATH=. ./a.out?
Makefile
.PHONY: allall: build targetbuild: libmymath.so libmymath.so: add.o subtract.ogcc -o $@ -shared $^ add.o: add.cgcc -c -fPIC $< subtract.o: subtract.cgcc -c -fPIC $<target: a.out a.out: main.cgcc main.c -L. -lmymath.PHONY: clean clean:rm *.o a.out libmymath.so?
轉載于:https://www.cnblogs.com/zuofaqi/p/10440754.html
總結
以上是生活随笔為你收集整理的linux动态链接库的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【flutter】学习之路(一)环境的搭
- 下一篇: java:提示Could not ini