靜態庫和動態庫的優缺點


一、庫的類型

(一) 在windows中

.dll 動態庫

.lib 靜態庫

庫即為源代碼的二進制文件

(二) 在linux中

.so 動態庫

.a      靜態庫

 

(三) 靜態庫和動態庫的優缺點

我們通常把一些公用函數制作成函數庫,供其它程序使用。

函數庫分為靜態庫和動態庫兩種。

靜態庫在程序編譯時會被連接到目標代碼中,程序運行時將不再需要該靜態庫。

動態庫在程序編譯時並不會被連接到目標代碼中,而是在程序運行是才被載入,因此在程序運行時還需要動態庫存在

 

1.什么是庫

在windows平台和linux平台下都大量存在着庫。

本質上來說庫是一種可執行代碼的二進制形式,可以被操作系統載入內存執行。

由於windows和linux的本質不同,因此二者庫的二進制是不兼容的。

本文僅限於介紹linux下的庫

 

2.庫的種類

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

 二者的不同點在於代碼被載入的時刻不同。

靜態庫的代碼在編譯過程中已經被載入可執行程序,因此體積較大。

共享庫的代碼是在可執行程序運行時才載入內存的,在編譯過程中僅簡單的引用,因此代碼體積較小。

 

3.庫存在的意義

庫是別人寫好的現有的,成熟的,可以復用的代碼,你可以使用但要記得遵守許可協議。

現實中每個程序都要依賴很多基礎的底層庫,不可能每個人的代碼都從零開始,因此庫的存在意義非同尋常。共享庫的好處是,不同的應用程序如果調用相同的庫,那么在內存里只需要有一份該共享庫的實例。

 

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 -olibfoo.so.1.0 *.

 

5.庫文件是如何命名的,有沒有什么規范

在linux下,庫文件一般放在/usr/lib和/lib下,

靜態庫的名字一般為libxxxx.a,其中xxxx是該lib的名稱

動態庫的名字一般為libxxxx.so.major.minor,xxxx是該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庫

 

7.可執行程序在執行的時候如何定位共享庫文件

當系統加載可執行代碼時候,能夠知道其所依賴的庫的名字,但是還需要知道絕對路徑

此時就需要系統動態載入器(dynamiclinker/loader)

對於elf格式的可執行程序,是由ld-linux.so*來完成的

它先后搜索elf文件的 DT_RPATH段—環境變量LD_LIBRARY_PATH—/etc/ld.so.cache文件列表—/lib/,/usr/lib目錄

找到庫文件后將其載入內存

 

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.oerrorlog.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.soerror.o errorlog.o

這樣就創建了共享庫!

2.編譯共享庫

    假設共享庫位於當前目錄(即跟程序文件相同的目錄中)

gcc -o test -L. -lapue test.c

這樣就編譯出了不包含函數代碼可執行文件了,但是但你運行時會發現linux動態加載器找不到libapue.so文件.

可以用ldd 命令查看可執行文件依賴什么共享庫:

ldd test

如何才能讓動態加載器發現庫文件呢?有兩種方法可以解決:

    1.環境變量

       exportLD_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

 

/*

參數的配置通過mangcc可以看到

-llibrary

              連接名為 library 的 庫文件.

              連接器 在 標准搜索目錄 中 尋找 這個 庫文件, 庫文件 的 真正 名 字


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM