1. 程式人生 > >靜態庫和共享庫

靜態庫和共享庫

靜態庫

把多個.o檔案打包成靜態庫,以libXXX.a的格式命名,程式連結時,會把靜態庫整合在可執行檔案中,程式執行時,會直接載入到記憶體中。

生成靜態庫

  • 靜態庫中新增或替換.o檔案
    ar r libXXX.a x1.o x2.o x3.o
    注:如果.o檔案不存在,就新增檔案,如果.o檔案已存在,就替換檔案。
  • 靜態庫中刪除.o檔案
    ar d libXXX.a x1.o
  • 檢視靜態庫
    ar tv libXXX.a
  • 提取靜態庫中的.o檔案
    ar x libXXX.a x1.o

使用靜態庫

  • 方法1:直接使用
    gcc a.c libXXX.a

  • 方法2:連結使用
    gcc a.c -L靜態庫檔案所在目錄 -l靜態庫名
    注意:libXXX.a的靜態庫名為XXX

共享庫

把多個.o檔案打包成共享庫,以libXXX.so的格式命名,程式連結時,不會把共享庫整合在可執行檔案中,程式執行時,如果呼叫共享庫中的函式,此時會把共享庫載入到記憶體。

生成共享庫

  • 生成與位置無關的.o檔案
    gcc -c -fPIC a.c -o a.o
    注意:共享庫必須使用與位置無關的.o檔案
  • 打包共享庫
    gcc -shared a.o b.o c.o -o libXXX.so
  • 檢視.o檔案是否使用-fPIC選項編譯
    nm a.o | grep _GLOBAL_OFFSET_TABLE_

    _GLOBAL_OFFSET_TABLE_,則表示使用了-fPIC選項

使用共享庫

  • 動態連結
    因可執行檔案不包含共享庫,所以需要某種機制找出共享庫所在路徑通知動態連結器
    方法1:環境變數:LD_LIBRARY_PATH
    方法2:配置檔案:/etc/ld.so.conf
    方法3:編譯時指定:gcc -Wl,rpath,/共享庫目錄

  • 直接使用
    gcc a.c libXXX.so

  • 連結使用
    gcc a.c -L共享庫目錄 -l共享庫名

帶有so-name的共享庫

  • 生成有so-name的共享庫
    gcc -shared -Wl,-soname,libBBB.so -o libAAA.so a.o b.o c.o


    -Wl,-soname,libBBB.so:指定共享庫AAA的so-name為BBB

  • 生成軟連結檔案
    ln -s libAAA.so libBBB.so

共享庫的版本控制

  • 真實名稱
    libXXX.so.1.0.1
    第一個數字:大版本號
    後兩個數字:修訂號

  • 真實名稱、so-name、連結名稱三者的關係
    真實名稱:libXXX.so.1.0.1,共享庫實際的檔案
    so-name:libXXX.so.1,區分大版本,不同大版本之間不相容
    連結名稱:libXXX.so,連結時使用,此名稱一直不變

  • 使用標準規範建立一個共享庫
    gcc -g -c -fPIC mod1.c mod2.c mod3.c
    gcc -g -shared -Wl,soname,libdemo.so.1 -o libdemo.so.1.0.1 mod1.o mod2.o mod3.o
    ln -s libdemo.so.1.0.1 libdemo.so.1
    ln -s libdemo.so.1 libdemo.so

  • 安裝共享庫
    cp libXXX.so.1.0.1 /指定目錄
    ln -s libXXX.so.1.0.1 /指定目錄/libXXX.so.1
    ln -s libXXX.so.1 /指定目錄/libXXX.so

  • 共享庫安裝路徑
    /lib
    /usr/lib
    /usr/local/lib

  • 共享庫升級小版本
    編譯好小版本後,放入指定路徑
    執行ldconfig -v可以自動更新小版本

  • 共享庫升級大版本
    拷貝libXXX.so.2.0.0放入指定路徑
    執行ldconfig -v更新,會生成libXXX.so.2軟連結
    執行ln -s libXXX.so.2 libXXX.so

混合連結靜態庫、共享庫

當靜態庫和共享庫同名時,編譯器預設會優先使用共享庫,如果共享庫不存在,則使用靜態庫。

  • 全部使用靜態庫
    gcc a.c -static -L庫目錄 -lXXX
  • 混合使用靜態庫、共享庫
    gcc a.c -L庫目錄 -Wl,-dn -lX1 -Wl,-dy -lX2
    -Wl,-dn:表示開始使用靜態庫
    -Wl,-dy:表示結束使用靜態庫
    注意:-Wl,-dn 和 -Wl,-dy要成對出現