linux下靜態庫、動態庫相關問題總結

來源:互聯網
上載者:User

  前段時間項目中用到了對方給的庫檔案,從最初的不會用到現在小有心得,並且在看了網上很多大牛的部落格後,總結下發在這裡。

下一篇會發一篇關於在交叉編譯環境下,靜態庫和動態庫載入的問題。

 

一、靜態庫、動態庫的概念

      庫檔案是一些函數、變數的集合,已編譯過的代碼。一般分為靜態庫和動態庫兩種。

靜態庫: 靜態是指每個用到該庫的應用程式都擁有一份自己的庫拷貝;應用程式啟動並執行時候,即使將庫刪除也沒有問題,因為應用程式自己已經有了自己的拷貝。但是這也稱為了它的缺點,因為靜態庫如果發生改變的話,那麼應用程式也就需要重新進行編譯了

 

動態庫: 一個共用庫有可能被多個所有應用程式共用。因此,對每個應用程式來說,即使不再使用某個共用庫,也不應將其刪除。此外,應用程式需要正確的環境變數設定(LD_LIBRARY_PATH),從而找到共用庫所在的位置,否則,應用程式運行時會報告找不到這個庫。

 

二、靜態庫、動態庫的建立

建立:
無論靜態庫還是動態庫,建立都分為兩步,第一步建立目標檔案,第二步生產庫。
1).靜態庫的建立:
#gcc -c test.c -o test.o
#ar rcs libtest.a test.o
名字為libtest.a的靜態庫就生產了,其中選項:
r 表明將模組加入到靜態庫中;
c 表示建立靜態庫;
s 表示生產索引;
還有更多選項像增加、刪除庫中的目標檔案,包括將靜態庫解包等可以通過man來獲得。

2).動態庫的建立:
#gcc -fPIC -c test.c -o test.c
#gcc --share test.o -o libtest.so
-fPIC 為了跨平台

 

三、靜態庫、動態庫的使用

 環境變數配置:

庫檔案在串連(靜態庫和共用庫)和運行(僅限於使用共用庫的程式)時被使用,其搜尋路徑是在系統中進行設定的。
一般 Linux 系統把 /lib 和 /usr/lib 兩個目錄作為預設的庫搜尋路徑,所以使用這兩個目錄中的庫時不需要進行設定搜尋路徑即可直接使用。對於處於預設庫搜尋路徑之外的庫,需要將庫的位置添加到庫的搜尋路徑之中。設定庫檔案的搜尋路徑有下列兩種方式,可任選其一使用:
在環境變數 LD_LIBRARY_PATH 中指明庫的搜尋路徑。 比如一個libtest.a庫在/home/test/lib目錄下,在終端內

$ export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/home/test/lib
在 /etc/ld.so.conf 檔案中添加庫的搜尋路徑。添加方法也極其簡單,將庫檔案的絕對路徑直接寫進去就OK了,一行一個,例如:

/usr/local/lib
/opt/lib

需要注意的是:第二種搜尋路徑的設定方式對於程式串連時的庫(包括共用庫和靜態庫)的定位已經足夠了,但是對於使用了共用庫的程式的執行還是不夠的。這是因為為了加快程式執行時對共用庫的定位速度,避免使用搜尋路徑尋找共用庫的低效率,所以是直接讀取庫列表檔案 /etc/ld.so.cache 從中進行搜尋的。/etc/ld.so.cache 是一個非文本的資料檔案,不能直接編輯,它是根據 /etc/ld.so.conf 中設定的搜尋路徑由 /sbin/ldconfig 命令將這些搜尋路徑下的共用庫檔案集中在一起而產生的(ldconfig 命令要以 root 許可權執行)。

        因此,為了保證程式執行時對庫的定位,在 /etc/ld.so.conf 中進行了庫搜尋路徑的設定之後,還必須要運行 /sbin/ldconfig 命令更新 /etc/ld.so.cache 檔案之後才可以。ldconfig ,簡單的說,它的作用就是將/etc/ld.so.conf列出的路徑下的庫檔案快取到/etc/ld.so.cache 以供使用。因此當安裝完一些庫檔案,(例如剛安裝好glib),或者修改ld.so.conf增加新的庫路徑後,需要運行一下 /sbin/ldconfig使所有的庫檔案都被緩衝到ld.so.cache中,如果沒做,即使庫檔案明明就在/usr/lib下的,也是不會被使用的,結果編譯過程中抱錯,缺少xxx庫,去查看發現明明就在那放著,這時候會很是鬱悶的。

 

 使用:
編譯連結目標程式的方法是一樣的:
#gcc main.c -L. -ltest -o main
-L.指定現在本目錄下搜尋庫,如果沒有,會到系統預設的目錄下搜尋,一般為/lib、/usr/lib下。
對於靜態庫,這個步驟之後就可以將libtest.a庫刪掉,因為它已經被編譯進了目標程式,不再需要它了。
而對於動態庫,libtest.so庫只是在目標程式裡做了標記,在運行程式時才會動態載入,那麼從哪載入呢?載入目錄會由/etc/ld.so.conf來指定,一般預設是/lib、/usr/lib,所以要想讓動態庫順利載入,你可以將庫檔案copy到上面的兩個目錄下,或者設定export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/XXX/YYY,後面為你自己動態庫的目錄,再或者修改/etc/ld.so.conf檔案,把庫所在的路徑加到檔案末尾,並執行ldconfig重新整理。這樣,加入的目錄下的所有庫檔案都可見。

 

四、靜態庫、動態庫的載入順序

GCC在連結過程中,對參數中的庫的順序是有要求的,參數右側的庫會先於左側的庫載入,也就是說參數的解析是從右往左的。

    假設庫B依賴與庫A,則連結的時候要寫為:
       gcc -o bin B A
   如果寫為:
       gcc -o bin A B
   則在B中引用的A中的內容就會無法連結通過如果在同一目錄下,既有靜態庫又有動態庫,則在預設情況下是先載入動態庫,因為對gcc來說預設是載入動態庫,如果要讓靜態庫優先載入的話,則需要加上-static參數
相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.