1.共享代碼
隨著軟件開發(fā)的發(fā)展,人們發(fā)現(xiàn)很多應用的代碼是相同的,也就是說這些代碼可以被共享,因此,人們提出了靜態(tài)庫和動態(tài)庫兩種方案來解決代碼共享的問題。
編輯搜圖
2.靜態(tài)庫
靜態(tài)庫,顧名思義,它是靜態(tài)的,也就是說它不會被動態(tài)編譯,它只會靜態(tài)編譯,節(jié)省了編譯時間,提高了編譯速度。同一份靜態(tài)庫,可以被多個程序進行編譯,也就實現(xiàn)了代碼的復用共享。
編輯搜圖
3.動態(tài)庫
動態(tài)庫,就是程序應用啟動的時候,動態(tài)加載的,因為它一般是在系統(tǒng)運行的時候就已經(jīng)運行的動態(tài)庫,因此其它應用可以直接使用它,并且同一個動態(tài)庫可以被多個應用共享使用,在系統(tǒng)中對于一個動態(tài)庫只會存在一份,這大大節(jié)省了內(nèi)存空間,大大提升了系統(tǒng)的性能。
在linux系統(tǒng)中,動態(tài)庫一般以.so形式命名,表示share object。
編輯搜圖
很多時候,你很難知道一個應用需要哪些動態(tài)庫,不過我們有個工具ldd可以幫助你查看一個應用需要哪些動態(tài)庫。
如果一些動態(tài)庫沒有找到的話,程序就無法正常運行,這也是你會看到很多程序啟動的時候提示缺少xx.so的原因。
如果你的程序需要xx.so動態(tài)庫,而系統(tǒng)路徑中沒有它的話,你可以通過LD_LIBRARY_PATH 將你需要的動態(tài)庫添加到系統(tǒng)路徑中。
編輯搜圖
查看一個文件使用了什么連接器可以使用file命令,一般程序都會使用/lib64/ld-linux-x86-64.so.2這個文件,而這個文件其實會指向一個ld-2.xx.so文件。
4.動態(tài)加載器ld.so
在linux系統(tǒng)中,動態(tài)庫都是通過ld.so來進行管理的,它首先會根據(jù)應用的編譯信息查找相對或者絕對路徑來查找動態(tài)庫,然后就會通過環(huán)境變量LD_LIBRARY_PATH來查找動態(tài)庫,最后它會根據(jù)/etc/ld.so.cache緩存來查找動態(tài)庫。
因此,當我們像系統(tǒng)中添加一個動態(tài)庫的時候我們有兩種方式,一種是直接放入到/usr/lib64文件夾里面,不過這需要你有root權限,第二種就是通過LD_LIBRARY_PATH配置我們的動態(tài)庫路徑。
5.程序引入動態(tài)庫
在程序編譯的時候,我們可以通過指定編譯參數(shù)來引入動態(tài)庫。
例如,當我們使用gcc來進行編譯的時候,我們可以通過-l來表示鏈接庫名稱,通過-Ldir來指定動態(tài)庫路徑。 當我們使用g++來進行編譯的時候,-L可以用來指定動態(tài)庫的路徑,進行程序動態(tài)庫的鏈接。
6.總結
人們?yōu)榱藴p少冗余代碼,提出了共享庫的概念,在鏈接的時候和程序一同打包成一個可執(zhí)行文件的這個庫就是靜態(tài)庫,反之,在鏈接的時候不將動態(tài)庫打包進可執(zhí)行文件,只是標記運行需要此共享庫,這就是動態(tài)庫。
靜態(tài)庫是同程序一同打包的,因此它不需要環(huán)境的依賴,而動態(tài)庫是程序執(zhí)行時候需要引用的,因此它對環(huán)境有依賴,這也是為什么很多依賴動態(tài)庫的文件執(zhí)行的時候報錯缺少動態(tài)庫的原因,那是操作系統(tǒng)缺少對應的動態(tài)庫導致的。
靜態(tài)庫增大了程序的體積,同時多個程序對相同靜態(tài)庫的鏈接也占用了大量的內(nèi)存,因此,才有了動態(tài)庫的出現(xiàn),可以說兩者都是為了解決代碼共享復用的問題,而且兩者是相輔相成的關系。