Windows XP Windows 7 Windows 2003 Windows Vista Windows 綜合教學 Linux 系統教學
Windows 10 Windows 8 Windows 2008 Windows NT Windows Server 電腦軟體教學
您现在的位置: Windows教程網 >> Windows教程 >  >> Linux 系統教學 >> 關於 Linux

Linux 動態函式庫 建立與鏈結實戰:從 .so 產生到執行期載入

編輯:關於 Linux

動態函式庫 (.so) 能減少磁碟/記憶體佔用、方便升級、提升 CPU 快取命中率。本文以 Ubuntu 14.04 + GCC 4.8 為例,完整示範 .so 編譯、鏈結、執行期載入路徑設定與常見錯誤排查。

動態函式庫 基本概念

  • 檔名慣例:lib名稱.so (可含版號,如 libfoo.so.1.0)。
  • 對應靜態庫:lib名稱.a。
  • 編譯關鍵參數:-fPIC (位置無關程式碼)、-shared (產生共享物件)。
  • 鏈結時指定 -l名稱 (省略 lib 前綴與 .so 後綴)。

實戰範例程式碼

目錄結構


/home/test/program/
├── myLibSrc.c      # 函式庫原始碼
├── myLibInclude.h  # 標頭檔
└── main.c          # 測試主程式

myLibInclude.h


#ifndef MYLIB_H
#define MYLIB_H
int myLibSrcFun(void);
#endif

myLibSrc.c


#include 
#include "myLibInclude.h"

int myLibSrcFun(void) {
    printf("There is myLibSrcFun()\n");
    return 0;
}

main.c


#include 
#include "myLibInclude.h"

int main(int argc, char **argv) {
    printf("Main function!\n");
    myLibSrcFun();  // 呼叫動態庫函式
    return 0;
}

編譯動態函式庫


cd /home/test/program
gcc -fPIC -shared -o libmyLib.so myLibSrc.c
# 或加入除錯資訊
gcc -fPIC -shared -g -DDEBUG -o libmyLib.so myLibSrc.c
  • -fPIC:產生位置無關程式碼,供多進程共享同一記憶體映射。
  • -shared:指示連結器產生共享物件而非執行檔。

編譯主程式並鏈結動態庫

方法一:指定完整路徑


gcc -o app main.c /home/test/program/libmyLib.so
./app
# 輸出:
# Main function!
# There is myLibSrcFun()

方法二:安裝至系統庫目錄


cp libmyLib.so /usr/lib/libmyLib.so
gcc -o app main.c -lmyLib

編譯器會在 /usr/lib, /usr/local/lib, /lib 等標準路徑尋找 libmyLib.so。

執行期動態載入器 尋找順序

  1. LD_LIBRARY_PATH 環境變數指定的目錄 (最高優先)。
  2. /etc/ld.so.cache 快取 (由 ldconfig 產生)。
  3. 預設系統目錄 /lib, /usr/lib (64-bit 為 /lib64, /usr/lib64)。

將自訂庫目錄加入系統快取


echo "/home/test/program" > /etc/ld.so.conf.d/myLib.conf
ldconfig
# 現在可直接 -lmyLib 鏈結,執行時也能找到

執行期指定路徑 (不修改系統設定)


LD_LIBRARY_PATH=/home/test/program ./app

進階主題

版本控制與 soname


# 編譯時指定 soname
gcc -fPIC -shared -Wl,-soname,libmyLib.so.1 -o libmyLib.so.1.0 myLibSrc.c

# 建立符號連結
ln -sf libmyLib.so.1.0 libmyLib.so.1
ln -sf libmyLib.so.1 libmyLib.so

執行期載入器依 soname (此例 libmyLib.so.1) 尋找實際檔案,實現主版本相容、次版本升級。

dlopen/dlsym 動態載入 (Plugin 架構)


#include 
void *handle = dlopen("./libmyLib.so", RTLD_LAZY);
int (*func)(void) = dlsym(handle, "myLibSrcFun");
func();
dlclose(handle);

編譯需加 -ldl。適用於插件系統、熱插拔模組。

常見錯誤與排查

錯誤訊息原因解決
error while loading shared libraries: libmyLib.so: cannot open shared object file執行期找不到 .so設定 LD_LIBRARY_PATH、執行 ldconfig、或安裝至 /usr/lib
/usr/bin/ld: cannot find -lmyLib編譯/鏈結期找不到指定 -L/path/to/lib 或複製至標準目錄
undefined reference to `myLibSrcFun'函式簽名不符或未鏈結確認標頭檔宣告、.c 定義、鏈結順序

動態函式庫編譯鏈結流程圖

Copyright © Windows教程網 All Rights Reserved