Linux下的靜態庫、動態庫和動態載入庫
Linux庫型別
Linux下可以建立兩種型別的庫:
- 靜態庫
(.a)
: 在連結期間被應用程式直接連結進可執行檔案 - 動態連結庫
(.so)
: 動態庫還分為兩種用法: a) 應用程式執行期間連結動態庫,但是在編譯期間宣告動態庫的存在,也就是說這種動態庫必須在編譯時對編譯器可見,但編譯器卻不將此種庫編譯進可執行檔案; b) 在執行期間,動態載入和解除安裝的庫,使用動態載入方法載入。這種庫的形式跟動態連結沒有本質區別,區別是在呼叫時,是由使用者程式決定何時連結的,而不是由系統連結器自動連結
命名約定
庫需要以lib
作為開頭,而在指定連結命令列引數時,卻無需包含開頭和副檔名,例如:
gcc src-file.c -lm -lpthread
這個例子中,連結了libmath.a
和libpthread.a
靜態庫(.a)
生成靜態庫的方法如下:
- 編譯object檔案。例如:
cc -Wall -c ctest1.c ctest2.c
,該命令會生成ctest1.o
和ctest2.o
(其中-Wall
表示編譯時輸出警告)。 - 建立庫檔案。例如:
ar -cvq libctest.a ctest1.o ctest2.o
。該命令會得到一個libctest.a
檔案 - 可以通過
ar -t
檢視.a
檔案中包含哪些.o
。所以,實際上ar
就是一個打包命令,類似tar
- 構建符號表。
ranlib libctest.a
用於為.a
建立符號表。有些ar命令實際上已經整合了ranlib
的功能
.a
檔案與windows下的.lib
是相同的概念。
動態庫(.so)
生成動態庫的方法如下:
編譯object檔案時使用-fPIC
選項:
gcc -Wall -fPIC -c *.c
這個選項的目的是讓編譯器生成地址無關(position independent)的程式碼,這是因為,動態庫是在執行期間連結的,變數和函式的偏移量是事先不知道的,需要連結以後根據offset
進行地址重定向。
使用-shared
連結
gcc -shared -Wl,-soname,libctest.so.1 -o libctest.so.1.0 *.o
-shared
選項是讓動態庫得以在執行期間被動態連結;-Wl,options
是設定傳遞給ld(連結器)
的引數,在上面的例子中,當連結器在連結.o
時會執行ld -soname ibctest.so.1
建立軟鏈
上面的命令將最終輸出一個動態庫libctest.so.1.0
,而出於習慣,會建立兩個軟鏈:
mv libctest.so.1.0 /opt/lib ln -sf /opt/lib/libctest.so.1.0 /opt/lib/libctest.so.1 ln -sf /opt/lib/libctest.so.1.0 /opt/lib/libctest.so
libctest.so
用於在編譯期間使用-lctest
讓編譯器找到動態庫,而libctest.so.1
用於在執行期間連結
gcc -Wall -I/path/to/include-files -L/path/to/libraries prog.c -lctest -o prog
檢視依賴
使用ldd
命令來檢視程式對動態庫的依賴。例如:
ldd prog libctest.so.1 => /opt/lib/libctest.so.1 (0x00002aaaaaaac000) libc.so.6 => /lib64/tls/libc.so.6 (0x0000003aa4e00000) /lib64/ld-linux-x86-64.so.2 (0x0000003aa4c00000)
obj檔案
obj檔案的格式和組成可能是系統差異性的一大體現,比如windows
下的PE
、linux
和一些unix
下的elf
、macos
的mach-o
、aix
下的xcoff
。
檢視obj檔案的符號表資訊,可以通過nm
objdump
readelf
等方法。
執行期間查詢動態庫
執行期間,系統需要知道到哪裡去查詢動態庫,這是通過/etc/ld.so.conf
配置的。ldconfig
用於配置執行時動態庫查詢路徑,實際是更新/etc/ld.so.cache。另外一些環境變數也可以影響查詢:(Linux/Solaris: LD_LIBRARY_PATH
, SGI: LD_LIBRARYN32_PATH
, AIX:LIBPATH
, Mac OS X: DYLD_LIBRARY_PATH
, HP-UX: SHLIB_PATH
)
動態載入和解除安裝的庫
需要應用程式希望設計成外掛化的架構,這就需要可以動態載入和解除安裝庫的機制。與動態連結不同的是,動態載入的意思是,編譯期間可以對動態庫的存在一無所知,而是在執行期間通過使用者程式嘗試載入進來的。
通過dlfcn.h
中的dlopen
、dlsym
和dlclose
等函式實現此種功能。
另外,使用到dlfcn
機制的可執行檔案需要使用-rdynamic
選項,它將指示聯結器把所有符號(而不僅僅只是程式已使用到的外部符號,但不包括靜態符號,比如被static修飾的函式)都新增到動態符號表(即.dynsym表)裡。
GNU Libtool
如今許多軟體的編譯都採用libtool
工具,libtool是一個編譯連結包裝工具,實際只是一個指令碼,用libtool編譯和連結會產生類似.la
的檔案,.la
這種檔案其實是個文字檔案,指向.a
檔案,並宣告一些版本資訊。
相關文章
- Linux 依賴動態庫 / 靜態庫的動態態庫 / 靜態庫Linux
- Linux下的共享庫(動態庫)和靜態庫Linux
- 簡述Linux下的靜態庫和動態庫Linux
- linux下的靜態庫與動態庫Linux
- Linux環境下建立靜態庫和動態庫Linux
- ios靜態庫和動態庫iOS
- android下java的靜態庫和動態庫AndroidJava
- cmake:生成靜態庫和動態庫
- 動態庫和靜態庫的區別
- 在Linux中建立靜態庫和動態庫Linux
- Linux共享庫、靜態庫、動態庫詳解Linux
- iOS動態庫和靜態庫的運用iOS
- Linux靜態庫和動態庫學習總結Linux
- Windows靜態庫和動態庫的建立和使用Windows
- Linux下建立靜態庫、動態庫以及簡單的makefileLinux
- linux 動態庫 靜態庫 函式覆蓋Linux函式
- linux下靜態庫、動態庫編譯及makefile書寫Linux編譯
- iOS中的動態庫,靜態庫和framework介紹iOSFramework
- 一、靜態庫和動態庫,Makefile專案管理專案管理
- linux下靜態連結庫和動態連結庫的區別有哪些Linux
- ios靜態庫與動態庫的區別iOS
- 動態連結庫和靜態連結庫的區別
- 動態連結庫與靜態連結庫
- 菜鳥教程——iOS動態庫與靜態庫iOS
- iOS 靜態庫(.a, .framework) 動態庫(.framework, dylib)iOSFramework
- Linux 中的靜態庫和動態庫簡介及生成過程示例Linux
- Android NDK祕籍--淺析靜態庫和動態庫Android
- Xcode新增Shell指令碼打包靜態庫和動態庫XCode指令碼
- Linux 動態庫與靜態庫製作及使用詳解Linux
- linux成長之路(gcc編譯器、靜態庫、動態庫)LinuxGC編譯
- Linux下動態共享庫 連線和載入路徑Linux
- 使用dlopen載入動態庫
- QLibrary 載入動態庫
- 動態庫載入過程
- C++靜態庫與動態庫深入研究C++
- 靜態庫和動態庫的製作以及Bundle資原始檔的使用
- ios 開發中 動態庫 與靜態庫的區別iOS
- VS下生成與配置靜態庫與動態庫(一)