關於linux下的共享庫(動態庫)和靜態庫

 

1.什麼是庫
windows平臺和linux平臺下都大量存在着庫。
質上來講庫是一種可執行代碼的二進制形式,能夠被操做系統載入內存執行。
因爲windowslinux的本質不一樣,所以兩者庫的二進制是不兼容的
本文僅限於介紹linux下的庫linux

 

2.庫的種類
linux
下的庫有兩種:靜態庫和共享庫(動態庫)。windows

 兩者的不一樣點在於代碼被載入的時刻不一樣。
靜態庫的代碼在編譯過程當中已經被載入可執行程序,所以體積較大。
共享庫的代碼是在可執行程序運行時才載入內存的,在編譯過程當中僅簡單的引用,所以代碼體積較小。函數

 

3.庫存在的意義
是別人寫好的現有的,成熟的,能夠複用的代碼,你可使用但要記得遵照許可協議。
現實中個程序都要依賴不少基礎的底層庫不可能每一個人的代碼都從零開始,所以庫的存在乎義非同尋常。共享庫的好處是,不一樣的應用程序若是調用相同的庫,那麼在內存裏只須要有一份該共享庫的實例。spa

 

4.庫文件是如何產生的在linux
靜態庫的後綴是.a,它的產生分兩步
Step 1.
源文件編譯生成一堆.o,每一個.o裏都包含這個編譯單元的符號表
Step 2.ar
命令將不少.o轉換成.a,成文靜態庫
動態庫的後綴是.so,它由gcc加特定參數編譯產生
例如:
$ gcc -fPIC -c *.c $ gcc -shared -Wl,-soname, libfoo.so.1 -o libfoo.so.1.0 *.
操作系統

 

5.庫文件是如何命名的,有沒有什麼規範
linux下,庫文件通常放在/usr/lib和/lib下,
靜態庫的名字通常爲libxxxx.a,其中xxxx是該lib的名稱
動態庫的名字通常爲libxxxx.so.major.minorxxxx是該lib的名稱,major是主版本號, minor是副版本號命令行

 

6.如何知道一個可執行程序依賴哪些庫
ldd
命令能夠查看一個可執行程序依賴的共享庫,
例如# ldd /bin/lnlibc.so.6
=> /lib/libc.so.6 (0×40021000)/lib/ld-linux.so.2
=> /lib/ld- linux.so.2 (0×40000000)
能夠看到ln命令依賴於libc庫和ld-linux
orm

 

7.可執行程序在執行的時候如何定位共享庫文件
當系統加載可執行代碼時候,可以知道其所依賴的庫的名字,可是還須要知道絕對路徑
此時就須要系統動態載入器(dynamic linker/loader)
對於elf格式的可執行程序,是由ld-linux.so*來完成的
索引

它前後搜索elf文件的 DT_RPATH環境變量LD_LIBRARY_PATH—/etc/ld.so.cache文件列表—/lib/,/usr/lib目錄內存

找到庫文件後將其載入內存ci

 

8.在新安裝一個庫以後如何讓系統可以找到他
若是安裝在/lib或者/usr/lib下,那麼ld默認可以找到,無需其餘操做
若是安裝在其餘目錄,須要將其添加到/etc/ld.so.cache文件中,步驟以下
1.
編輯/etc/ld.so.conf文件,加入庫文件所在目錄的路徑
2.
運行ldconfig,該命令會重建/etc/ld.so.cache文件

  

############################################################

  

 linux中編譯靜態庫(.a)和動態庫(.so)的基本方法

 

靜態庫 
 

linux環境中, 使用ar命令建立靜態庫文件.以下是命令的選項:
          d -----
從指定的靜態庫文件中刪除文件

          m -----
把文件移動到指定的靜態庫文件中

          p -----
把靜態庫文件中指定的文件輸出到標準輸出

          q -----
快速地把文件追加到靜態庫文件中

          r -----
把文件插入到靜態庫文件中

          t -----
顯示靜態庫文件中文件的列表

          x -----
從靜態庫文件中提取文件

     
還有多個修飾符修改以上基本選項,詳細請man ar 如下列出三個
:
          a -----
把新的目標文件(*.o)添加到靜態庫文件中現有文件以後

          b -----***************************************
以前

          v -----
使用詳細模式

ar 命令的命令行格式以下:
      ar [-]{dmpqrtx}[abcfilNoPsSuvV] [membername] [count] archive files...
參數archive定義庫的名稱, files是庫文件中包含的目標文件的清單, 用空格分隔每一個文件
.
 

好比建立一個靜態庫文件的命令以下:
      ar r libapue.a error.o errorlog.o lockreg.o
這樣就了libapue.a靜態庫文件, 能夠用 t 選項顯示包含在庫中的文件
 
建立庫文件以後,能夠建立這個靜態庫文件的索引來幫助提升和庫鏈接的其餘程序的編譯速度

使用ranlib程序建立庫的索引,索引存放在庫文件內部.
      ranlib libapue.a
 

nm程序顯示存檔文件的索引,它能夠顯示目標文件的符號
nm libapue.a | more
若是是顯示目標文件的符號
:
nm error.o | more
如何使用呢?以下所示
:
gcc -o test test.c libapue.a
這樣就能夠在test.c中調用在libapue.a中的函數了.

  

 

動態庫


1.
建立共享庫

     gcc -shared -o libapue.so error.o errorlog.o
這樣就建立了共享庫
!
2.
編譯共享庫

   
假設共享庫位於當前目錄(即跟程序文件相同的目錄中
)
gcc -o test -L. -lapue test.c
這樣就編譯出了不包含函數代碼可執行文件了,可是但你運行時會發現linux動態加載器找不到libapue.so文件
.
能夠用ldd 命令查看可執行文件依賴什麼共享庫
:
ldd test
如何才能讓動態加載器發現庫文件呢?有兩種方法能夠解決

    
1.環境變量
       export LD_LIBRARY_PATH="$LD_LIBRARY_PATH:."
    2.
修改/etc/ld.so.conf文件.

  

通常應用程序的庫文件不與系統庫文件放在同一個目錄下,通常把應用程序的共享庫文件放在/usr/local/lib,新建一個屬於本身的目錄apue,而後把剛纔libapue.so複製過去就好了
同時/etc/ld.so.conf中新增一行
:
/usr/local/lib/apue


之後在編譯程序時加上編譯選項
:
-L /usr/local/lib/apue -lapue

 

/*

參數的配置經過man gcc能夠看到

-llibrary

              鏈接名爲 library 庫文件. 

              鏈接器 標準搜索目錄 尋找 這個 庫文件, 庫文件 真正

相關文章
相關標籤/搜索