這篇文章主要講解了“l(fā)inux下靜態(tài)鏈接庫和動態(tài)鏈接庫的區(qū)別有哪些”,文中的講解內(nèi)容簡單清晰,易于學(xué)習(xí)與理解,下面請大家跟著小編的思路慢慢深入,一起來研究和學(xué)習(xí)“l(fā)inux下靜態(tài)鏈接庫和動態(tài)鏈接庫的區(qū)別有哪些”吧!
10年積累的成都做網(wǎng)站、成都網(wǎng)站制作經(jīng)驗(yàn),可以快速應(yīng)對客戶對網(wǎng)站的新想法和需求。提供各種問題對應(yīng)的解決方案。讓選擇我們的客戶得到更好、更有力的網(wǎng)絡(luò)服務(wù)。我雖然不認(rèn)識你,你也不認(rèn)識我。但先網(wǎng)站設(shè)計(jì)后付款的網(wǎng)站建設(shè)流程,更有全椒免費(fèi)網(wǎng)站建設(shè)讓你可以放心的選擇與我們合作。
區(qū)別:1、動態(tài)庫的后綴為“.so”,靜態(tài)庫的后綴為“.a”。2、如果靜態(tài)函數(shù)庫改變了,那么程序必須重新編譯;而動態(tài)函數(shù)庫的改變并不影響程序。3、相對于靜態(tài)庫,動態(tài)庫在編譯的時(shí)候并沒有被編譯進(jìn)目標(biāo)代碼中,用戶的程序執(zhí)行到相關(guān)函數(shù)時(shí)才調(diào)用該函數(shù)庫里的相應(yīng)函數(shù),因此動態(tài)函數(shù)庫所產(chǎn)生的可執(zhí)行文件比較小。
一、庫的基礎(chǔ)概念:
在windows平臺和linux平臺下都大量存在著庫。本質(zhì)上來說庫是一種可執(zhí)行代碼的二進(jìn)制形式,可以被操作系統(tǒng)載入內(nèi)存執(zhí)行。由于windows和linux的本質(zhì)不同,因此二者庫的二進(jìn)制是不兼容的。通俗的說就是把這些常用函數(shù)的目標(biāo)文件打包在一起,提供相應(yīng)函數(shù)的接口,便于程序員使用。在使用函數(shù)時(shí),只需要包對應(yīng)的頭文件即可。按照庫的使用方式又可分為動態(tài)庫和靜態(tài)庫,在不同平臺下對應(yīng)后綴也有所不同。
WINDOWS下:.dll 后綴為動態(tài)庫,.lib 后綴為靜態(tài)庫;
LINUX下:.so
后綴為動態(tài)庫,.a
后綴為靜態(tài)庫。
二、靜態(tài)庫與靜態(tài)鏈接
<1>靜態(tài)庫:
靜態(tài)庫可以簡單的看成一組目標(biāo)文件的集合,即很多目標(biāo)文件經(jīng)過壓縮打包后形成的文件。比如在我們?nèi)粘>幊讨?,如果需要使用printf函數(shù),就需要包stdio.h的庫文件,使用strlen時(shí),又需要包string.h的庫文件,可是如果直接把對應(yīng)函數(shù)源碼編譯后形成的.o文件直接提供給我們,將會對我們的管理和使用上造成極大不便,于是可以使用“ar”壓縮程序?qū)⑦@些目標(biāo)文件壓縮在一起,形成libx.a靜態(tài)庫文件。
注:靜態(tài)庫命名格式:lib + "庫名稱”+ .a(后綴) 例:libadd.a就是一個(gè)叫add的靜態(tài)庫
<2>靜態(tài)鏈接:
對于靜態(tài)庫,程序在編譯鏈接時(shí),將庫的代碼鏈接到可執(zhí)行文件中,程序運(yùn)行時(shí)不再需要靜態(tài)庫。在使用過程中只需要將庫和我們的程序編譯后的文件鏈接在一起就可形成一個(gè)可執(zhí)行文件。
通過一個(gè)例子來了解下如何將我們自己寫的頭文件和代碼同時(shí)進(jìn)行編譯鏈接,最終生成可執(zhí)行文件:
/main.c/
#include
make后輸出截圖:
<3>缺點(diǎn):
1、內(nèi)存和磁盤空間浪費(fèi):靜態(tài)鏈接方式對于計(jì)算機(jī)內(nèi)存和磁盤的空間浪費(fèi)十分嚴(yán)重。
假如一個(gè)c語言的靜態(tài)庫大小為1MB,系統(tǒng)中有100個(gè)需要使用到該庫文件,采用靜態(tài)鏈接的話,就要浪費(fèi)進(jìn)100M的內(nèi)存,若數(shù)量再大,那浪費(fèi)的也就更多。例如下圖:程序1和程序2都需要用到Lib.o,采用靜態(tài)鏈接的話,那么物理內(nèi)存中就會存放兩份對應(yīng)此文件的拷貝。
2、更新麻煩:
比如一個(gè)程序20個(gè)模塊,每個(gè)模塊只有1MB,那么每次更新任何一個(gè)模塊,用戶都得重新下載20M的程序。
三、動態(tài)庫與動態(tài)鏈接
<1>動態(tài)庫:
程序在運(yùn)行時(shí)才去鏈接動態(tài)庫的代碼,多個(gè)程序共享庫的代碼。一個(gè)與動態(tài)庫鏈接的可執(zhí)行文件僅僅包含它用到的函數(shù)入口地址的一個(gè)表,而不是外部函數(shù)所在目標(biāo)文件的整個(gè)機(jī)器碼。
注:動態(tài)庫命名格式:lib + "庫名稱”+ .so(后綴) 例:libadd.so就是一個(gè)叫add的動態(tài)庫
<2>動態(tài)鏈接:
由于靜態(tài)鏈接具有浪費(fèi)內(nèi)存和模塊更新困難等問題,提出了動態(tài)鏈接?;緦?shí)現(xiàn)思想是把程序按照模塊拆分成各個(gè)相對獨(dú)立部分,在程序運(yùn)行時(shí)才將他們鏈接在一起形成一個(gè)完整的程序,而不是像靜態(tài)鏈接那樣把所有的程序模塊都鏈接成一個(gè)單獨(dú)的可執(zhí)行文件。所以動態(tài)鏈接是將鏈接過程推遲到了運(yùn)行時(shí)才進(jìn)行。
同樣,假如有程序1,程序2,和Lib.o三個(gè)文件,程序1和程序2在執(zhí)行時(shí)都需要用到Lib.o文件,當(dāng)運(yùn)行程序1時(shí),系統(tǒng)首先加載程序1,當(dāng)發(fā)現(xiàn)需要Lib.o文件時(shí),也同樣加載到內(nèi)存,再去加載程序2當(dāng)發(fā)現(xiàn)也同樣需要用到Lib.o文件時(shí),則不需要重新加載Lib.o,只需要將程序2和Lib.o文件鏈接起來即可,內(nèi)存中始終只存在一份Lib.o文件。
動態(tài)庫和動態(tài)鏈接的例子依然使用上面的代碼,輸出結(jié)果也相同,唯一需要改變的就是Makefile文件。
/Makefile/
main : main.c libadd.so
gcc main.c -L . -ladd -o main
libadd.so :
gcc -fPIC -shared add.c -o libadd.so
//-shared表示輸出結(jié)果是共享庫類型的 -fPIC表示使用地址無關(guān)代碼奇數(shù)來生產(chǎn)輸出文件
.PHONY:clean
clean:
rm main libadd.so
當(dāng)我們生成可執(zhí)行文件后,可使用ldd命令查看該可執(zhí)行文件所依靠的動態(tài)庫。
前面提到windows和Linux下庫文件的后綴不同,更根本的原因在于二者文件格式都不同??梢酝ㄟ^file一個(gè)動態(tài)庫查看Linux下動態(tài)庫的文件類型其實(shí)是ELF格式。ELF動態(tài)鏈接文件被稱為動態(tài)共享對象(DSO,Dynamic Shared Objects),簡稱共享對象;在windows下,動態(tài)鏈接文件被稱為動態(tài)鏈接庫(Dynamic Linking Library),也就是.dll文件后綴的全稱。
<3>優(yōu)點(diǎn):
①毋庸置疑的就是節(jié)省內(nèi)存;
②減少物理頁面的換入換出;
③在升級某個(gè)模塊時(shí),理論上只需要將對應(yīng)舊的目標(biāo)文件覆蓋掉即可。新版本的目標(biāo)文件會被自動裝載到內(nèi)存中并且鏈接起來;
④程序在運(yùn)行時(shí)可以動態(tài)的選擇加載各種程序模塊,實(shí)現(xiàn)程序的擴(kuò)展。
四、靜態(tài)庫和動態(tài)庫的區(qū)別
1. 靜態(tài)庫
這類庫的名字一般是 libxxx.a ;利用靜態(tài)函數(shù)庫編譯成的文件比較大,因?yàn)檎麄€(gè) 函數(shù)庫的所有數(shù)據(jù)都會被整合進(jìn)目標(biāo)代碼中,他的優(yōu)點(diǎn)就顯而易見了,即編譯后的執(zhí)行程序不需要外部的函數(shù)庫支持,因?yàn)樗惺褂玫暮瘮?shù)都已經(jīng)被編譯進(jìn)去了。當(dāng)然這也會成為他的缺點(diǎn),因?yàn)?如果靜態(tài)函數(shù)庫改變了,那么你的程序必須重新編譯 。
2. 動態(tài)庫
這類庫的名字一般是 libxxx.so ;相對于靜態(tài)函數(shù)庫,動態(tài)函數(shù)庫在編譯的時(shí)候并沒有被編譯進(jìn)目標(biāo)代碼中,你的程序執(zhí)行到相關(guān)函數(shù)時(shí)才調(diào)用該函數(shù)庫里的相應(yīng)函數(shù),因此動態(tài)函數(shù)庫所產(chǎn)生的可執(zhí)行文件比較小。由于函數(shù)庫沒有被整合進(jìn)你的程序,而是程序運(yùn)行時(shí)動態(tài)的申請并調(diào)用,所以程序的運(yùn)行環(huán)境中必須提供相應(yīng)的庫。 動態(tài)函數(shù)庫的改變并不影響你的程序,所以動態(tài)函數(shù)庫的升級比較方便。
感謝各位的閱讀,以上就是“l(fā)inux下靜態(tài)鏈接庫和動態(tài)鏈接庫的區(qū)別有哪些”的內(nèi)容了,經(jīng)過本文的學(xué)習(xí)后,相信大家對linux下靜態(tài)鏈接庫和動態(tài)鏈接庫的區(qū)別有哪些這一問題有了更深刻的體會,具體使用情況還需要大家實(shí)踐驗(yàn)證。這里是創(chuàng)新互聯(lián),小編將為大家推送更多相關(guān)知識點(diǎn)的文章,歡迎關(guān)注!