動態鏈接庫 VS 靜態鏈接庫

1、靜態庫與動態庫linux

一般狀況下,對函數庫的連接是放在編譯時期compile time)完成的。全部相關的對象文件(object file)與牽涉到的函數庫(library)被連接合成一個可執行文件executable file)。程序在運行時,與函數庫再無瓜葛,由於全部須要的函數已拷貝到本身門下。因此這些函數庫被成爲靜態庫(static libaray),一般文件名爲「libxxx.a」的形式。程序員

其實,咱們也能夠把對一些庫函數的連接載入推遲到程序運行時期runtime)。這就是如雷貫耳的動態連接庫(dynamic link library)技術。動態連接庫的名字形式爲 「libxxx.so」 後綴名爲 「.so」函數


1.動態連接庫有利於進程間資源共享spa

什麼概念呢?就是說,某個程序的在運行中要調用某個動態連接庫函數的時候,操做系統首先會查看全部正在運行的程序,看在內存裏是否已有此庫函數的拷貝了。若是有,則讓其共享那一個拷貝;只有沒有時才連接載入。這樣的模式雖然會帶來一些動態連接額外的開銷,卻大大的節省了系統的內存資源。C的標準庫就是動態連接庫,也就是說系統中全部運行的程序共享着同一個C標準庫的代碼段。操作系統

2. 將一些程序升級變得簡單。用靜態庫,若是庫發生變化,使用庫的程序要從新編譯。使用動態庫,只要動態庫提供給該程序的接口沒變,只要從新用新生成的動態庫替換原來就能夠了。orm

3. 甚至能夠真正坐到連接載入徹底由程序員在程序代碼中控制。
程序員在編寫程序的時候,能夠明確的指明何時或者什麼狀況下,連接載入哪一個動態連接庫函數。你能夠有一個至關大的軟件,但每次運行的時候,因爲不一樣的操做需求,只有一小部分程序被載入內存。全部的函數本着有需求才調入的原則,因而大大節省了系統資源。好比如今的軟件一般都能打開若干種不一樣類型的文件,這些讀寫操做一般都用動態連接庫來實現。在一次運行當中,通常只有一種類型的文件將會被打開。因此直到程序知道文件的類型之後再載入相應的讀寫函數,而不是一開始就將全部的讀寫函數都載入,而後才發覺在整個程序中根本沒有用到它們。對象

4.因爲靜態庫在編譯的時候,就將庫函數裝載到程序中去了,而動態庫函數必須在運行的時候才裝載,因此程序執行的時候,用靜態庫更快些。接口


3、靜態庫、動態庫的建立進程

不管靜態庫,仍是動態庫,都是由.o文件建立的。內存

靜態庫:

gcc –c file1.c file2.c

ar cr libxxx.a file1.o file2.o

動態庫:

因爲動態連接庫函數的共享特性(故又叫共享庫)它們不會被拷貝到可執行文件中。在編譯的時候,編譯器只會作一些函數名之類的檢查。在程序運行的時候,被調用的動態連接庫函數被安置在內存的某個地方,全部調用它的程序將指向這個代碼段。所以,這些代碼必須實用相對地址,而不是絕對地址。在編譯的時候,咱們須要告訴編譯器,這些對象文件是用來作動態連接庫的,因此要用地址不無關代碼(Position Independent Code PIC))
gcc編譯器,只需添加上 -fPIC 標籤,如:
gcc -fPIC -c file1.c
gcc -fPIC -c file2.c
gcc -shared libxxx.so file1.o file2.o

4、靜態庫和動態庫的使用

二者的使用相同:gcc –o main main.o libxxx.a(libxxx.so)

或者爲:gcc –o main main.o –L. –lxxxx

gcc file1.o file2.o -Lpath -lxxx -o program
編譯器會先到path目錄下搜索libxxx.so文件,若是沒有找到,繼續搜索libxxx.a(靜態庫)。

程序運行期間,也須要告訴系統去哪裏找你的動態連接庫文件。UNIX下是經過定義名爲 LD_LIBRARY_PATH 的環境變量來實現的。只需將path賦值給此變量便可。csh 命令爲:
setenv LD_LIBRARY_PATH your/full/path/to/dll
一切安排穩當後,你能夠用 ldd 命令檢查是否鏈接正常。
ldd program //
能夠看到它是如何調用動態庫中的函數的。

編譯參數解析:

-fPIC:表示編譯爲位置獨立的代碼,不用此選項的話編譯後的代碼是位置相關的因此動態載入時是經過代碼拷貝的方式來知足不一樣進程的須要,而不能達到真正代碼段共享的目的。
-Lpath
:表示在path目錄中搜索庫文件,如-L.則表示在當前目錄。

-Ipaht:表示在path目錄中搜索頭文件。
-ltest
:編譯器查找動態鏈接庫時有隱含的命名規則,即在給出的名字前面加lib,後面加上.so來肯定庫的名稱lLD_LIBRARY_PATH:這個環境變量指示動態鏈接器能夠裝載動態庫的路徑。
固然若是有root權限的話,能夠修改/etc/ld.so.conf文件,而後調用 /sbin/ldconfig來達到一樣的目的,不過若是沒有root權限,那麼只能採用輸出LD_LIBRARY_PATH的方法了。

注意:

調用動態庫的時候有幾個問題會常常碰到,有時,明明已經將庫的頭文件所在目錄 經過

「-I 「include進來了,庫所在目錄經過 「-L」參數引導,並指定了」-l」的庫名,但經過ldd命令察看時,就是死活找不到你指定連接的so文件,這時你要做的就是經過修改 LD_LIBRARY_PATH或者/etc/ld.so.conf文件來指定動態庫的目錄。一般這樣作就能夠解決庫沒法連接的問題了。特別注意在使用交叉編譯器編譯了一個程序後,當移植到ARM平臺運行時,因爲每每採用的是動態連接庫,在ARM平臺發現報錯,說找不到文件,實際上是由於程序所依賴的動態庫函數在ARM平臺的linux下沒有,每每解決的辦法有兩個:

1.在PC機,編譯時纔有靜態編譯,即加-static

2.將相應的動態庫文件同程序一塊兒移植到ARM平臺的linux中,而且要保證目錄

相關文章
相關標籤/搜索