Linux中的動態(tài)庫和靜態(tài)庫基礎概念
靜態(tài)庫(Static Library):
靜態(tài)庫是一種在編譯時將代碼直接鏈接到可執(zhí)行文件中的庫。
它通常以.a(Archive)為擴展名。
靜態(tài)庫在編譯時會被完整地復制到目標程序中,因此生成的程序體積較大。
優(yōu)點是運行時不需要額外的庫文件,便于部署和分發(fā)。
動態(tài)庫(Dynamic Library):
動態(tài)庫在編譯時并不會被直接鏈接到可執(zhí)行文件中,而是在程序運行時才加載。
它通常以.so(Shared Object)為擴展名。
動態(tài)庫允許多個程序共享同一份庫文件,節(jié)省內存空間。
優(yōu)點是更新和維護更為方便,只需替換庫文件即可影響所有使用該庫的程序。
動態(tài)庫與靜態(tài)庫的主要區(qū)別體現(xiàn)在鏈接時機、文件形式、資源占用及維護方式等方面:
鏈接時機
靜態(tài)庫在編譯時直接整合到可執(zhí)行文件中,而動態(tài)庫在運行時加載。 ?
文件形式
靜態(tài)庫通常以.a(Linux)或.lib(Windows)為擴展名,而動態(tài)庫以.so(Linux)或.dll(Windows)為擴展名。 ?
資源占用
靜態(tài)庫導致可執(zhí)行文件體積較大,但運行時無需外部依賴;動態(tài)庫文件較小且可被多個程序共享,但運行時依賴外部文件。 ?
更新維護
靜態(tài)庫更新后需重新編譯所有依賴程序;動態(tài)庫更新時只需替換庫文件,無需重新編譯主程序。 ?
運行效率
靜態(tài)庫調用無額外開銷,但動態(tài)庫首次調用時存在地址解析延遲。
相關優(yōu)勢
靜態(tài)庫的優(yōu)勢:
獨立性:程序不依賴于外部庫,便于部署。
性能:由于代碼直接嵌入程序中,運行時不需要額外的加載步驟,可能略微提高性能。
動態(tài)庫的優(yōu)勢:
共享性:多個程序可以共享同一份庫文件,節(jié)省磁盤空間和內存。
靈活性:更新庫文件時不需要重新編譯所有依賴它的程序。
維護性:庫的維護和升級更為方便。
類型與應用場景
靜態(tài)庫的應用場景:
對安全性要求較高的應用。
需要獨立部署且不經常更新的程序。
動態(tài)庫的應用場景:
大型軟件系統(tǒng),需要頻繁更新和維護的庫。
多個應用程序共享相同功能的場景。
示例代碼
創(chuàng)建靜態(tài)庫:
編寫源文件 mylib.c:
編寫源文件 mylib.c:
編譯成目標文件:
編譯成目標文件:
打包成靜態(tài)庫:
打包成靜態(tài)庫:
創(chuàng)建動態(tài)庫:
編寫源文件 mylib.c:
編寫源文件 mylib.c:
編譯成共享對象:
編譯成共享對象:
使用靜態(tài)庫:
編寫主程序 main.c:
編寫主程序 main.c:
鏈接靜態(tài)庫編譯:
鏈接靜態(tài)庫編譯:
使用動態(tài)庫:
編寫主程序 main.c:
編寫主程序 main.c:
鏈接動態(tài)庫編譯:
鏈接動態(tài)庫編譯:
運行時需確保動態(tài)庫路徑在 LD_LIBRARY_PATH 中:
運行時需確保動態(tài)庫路徑在 LD_LIBRARY_PATH 中:
遇到的問題及解決方法
問題:找不到動態(tài)庫文件
原因:系統(tǒng)無法找到動態(tài)庫文件,可能是因為庫文件不在標準路徑或未正確設置 LD_LIBRARY_PATH。
一、庫的基礎概念:
在windows平臺和linux平臺下都大量存在著庫。庫本質上是可執(zhí)行代碼的二進制形式,能夠被操作系統(tǒng)加載到內存中并執(zhí)行。由于Windows和Linux的基本差異,所以這兩個平臺的庫二進制文件不相容??梢院唵蔚乩斫鉃閷⑦@些常用函數(shù)的目標文件打包,并提供相應的函數(shù)接口,以方便程序員使用。在使用函數(shù)時,只需要包對應的頭文件即可。動態(tài)庫和靜態(tài)庫的使用方式不同,它們在不同平臺下的后綴也有所不同。
WINDOWS下:.dll 后綴為動態(tài)庫,.lib 后綴為靜態(tài)庫;
LINUX下:.so后綴為動態(tài)庫,.a后綴為靜態(tài)庫。
二、靜態(tài)庫與靜態(tài)鏈接
靜態(tài)庫:
簡單地說,靜態(tài)庫就是由多個目標文件打包壓縮而成的一個文件集合。比如在我們日常編程中,如果需要使用printf函數(shù),就需要包stdio.h的庫文件,使用strlen時,又需要包string.h的庫文件,可是如果直接把對應函數(shù)源碼編譯后形成的.o文件直接提供給我們,將會對我們的管理和使用上造成極大不便,于是可以使用“ar”壓縮程序將這些目標文件壓縮在一起,形成libx.a靜態(tài)庫文件。
注:靜態(tài)庫命名格式:lib + "庫名稱”+ .a(后綴) 例:libadd.a就是一個叫add的靜態(tài)庫
靜態(tài)鏈接:
靜態(tài)庫的代碼在編譯鏈接時被鏈接到可執(zhí)行文件中,程序運行時不再依賴靜態(tài)庫。只需將庫文件和程序編譯生成的文件鏈接,便可生成可執(zhí)行文件。
01庫的概述庫是代碼集合,為各種應用提供了豐富的功能,如我們熟知的ceres庫、eigen庫和pcl庫等。這些功能模塊作為可執(zhí)行代碼的二進制形式存在于系統(tǒng)中,并能被加載到內存中直接使用。在Linux系統(tǒng)中,庫主要分為動態(tài)鏈接庫和靜態(tài)鏈接庫兩大類。 動態(tài)庫和靜態(tài)庫的文件后綴分別為.so和.a。
02庫的差異
△ 靜態(tài)庫的特點
靜態(tài)庫在編譯階段被鏈接到目標代碼中,使得在程序運行時無需該庫。這種特性提高了程序的移植性,但可能會導致體積的增加,因為所有相關文件都會被鏈接成一個較大的可執(zhí)行文件。
△ 動態(tài)庫的特點
動態(tài)庫在運行時被加載,不會在編譯時被鏈接。這種方式減少了可執(zhí)行文件的體積,并且大多數(shù)常用的庫,如eigen和ceres,都采用動態(tài)鏈接的方式。在程序運行時,這些庫作為依賴項被使用。若環(huán)境中缺乏相應的動態(tài)庫,則需要 安裝對應的庫以解決編譯錯誤。
03靜態(tài)庫的創(chuàng)建與使用△ 創(chuàng)建過程
在Linux環(huán)境下,創(chuàng)建靜態(tài)庫涉及幾個關鍵步驟。首先,通過編譯器將 源文件編譯為目標文件,然后利用ar命令將這些目標文件歸檔成一個靜態(tài)庫文件。創(chuàng)建靜態(tài)庫的過程如下:
```
編寫源文件(.c或.cpp文件)
使用gcc -c xxx.c或g++ -c xxx.cpp生成目標文件(.o文件)
用ar命令將目標文件歸檔,生成靜態(tài)庫
編寫一個頭文件,包含提供給調用者的函數(shù)、變量或類的聲明
```
△ 使用過程
在使用靜態(tài)庫時, 需要在編譯時指定其路徑。同時也需注意靜態(tài)庫的版本兼容性問題,以確保程序能夠正確地調用其中的函數(shù)或變量。例如,在編寫調用靜態(tài)庫的程序時,應包含相應的頭文件,并在編譯指令中明確指定靜態(tài)庫的信息。
04動態(tài)庫的創(chuàng)建和使用△ 創(chuàng)建動態(tài)庫
創(chuàng)建動態(tài)庫需使用-fPIC參數(shù),編譯生成共享庫文件。具體過程如下:
```
g++ test.cpp -fPIC -shared -o libshowage.so
```
△ 使用動態(tài)庫
在程序 運行時要確保系統(tǒng)能找到共享對象文件。通常,將動態(tài)庫放在標準的庫路徑下如/usr/local/lib,或者在運行程序時明確指定庫的位置。通過設置庫路徑,可以解決動態(tài)庫無法被識別的問題。
05多個文件生成一個動態(tài)庫△ 多文件創(chuàng)建動態(tài)庫
在將多個文件整合為一個動態(tài)庫時,應 避免出現(xiàn)同名的聲明,否則編譯器將無法確定應使用哪個源文件中的聲明,導致無法成功創(chuàng)建動態(tài)庫。
△ 使用動態(tài)庫注意事項
使用動態(tài)庫時需要 注意函數(shù)調用和系統(tǒng)庫路徑,以確保程序在運行時能夠正確地加載所需的共享庫。這包括檢查動態(tài)庫的位置和確保相關的依存關系已安裝。
06安裝缺少的動態(tài)庫在編譯過程中若遇到類似“xxxx.h文件未找到”的錯誤,則很可能是缺少相應的庫。 通過終端命令安裝缺少的庫如libxxx-dev可以有效解決此類編譯錯誤。





