本文結合一個簡單樣本,說明了linux的動態連結程式庫的建立和使用問題,其中容易混淆的是編譯連結時的庫檔案路徑和運行期的庫檔案路徑問題。
1、建立自訂動態連結程式庫檔案(.so)和標頭檔
(1) 源檔案編寫。包括動態庫的源檔案 fred.c ,標頭檔fred.h 以及調用程式main.c
庫檔案實現源檔案 fred.c
#include <stdio.h>
void fred()
{
printf("fred is running../n");
}
庫檔案聲明標頭檔 fred.h
#ifndef __FRED_H__
#define __FRED_H__
#include <stdio.h>
void fred();
#endif
調用程式 main.c
#include "fred.h"
int main()
{
fred();
return 0;
}
(2)產生動態庫
命令: gcc -o libhello.so -O2 -fPIC -shared hello.c
其中-o 表示輸出檔案名為libhello.so,動態連結程式庫名稱必須按照libXX.so格式命名;-O2表示使用編譯器最佳化;
庫檔案、庫申明、調用程式都在同一檔案夾中
2、使用自訂動態連結程式庫
(1) 編譯 gcc -c -o main.c main.o
(2) 連結 gcc -o main main.o -L. -lfred
ldconfig做的這些東西都與運行程式時有關,跟編譯時間一點關係都沒有。編譯的時候還是該加-L就得加,不要混淆了
如果硬是要求不用使用-L參數,則可以在LD_LIBRARY_PATH中添加庫檔案所在的路徑,如:
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:./
gcc -o main main.o -lfred
(3) 運行 ./main
通過在/etc/ld.so.conf.d/下添加一個包含自libfred.so絕對路徑的檔案,並且運行ldconfig命令
如果沒有運行ldconfig,則運行main時出現找不到庫檔案libfred的錯誤。
(4) 總結:
使用動態連結程式庫的程式要想正確運行,需要注意程式不同時期的路徑問題:
a、連結期路徑: 通過-L或者LD_LIBRARY_PATH環境變數指定,使得gcc可以找到動態連結程式庫檔案
b、運行期路徑: 通過在/etc/ld.so.conf.d/下添加一個包含自訂連結庫絕對路徑的檔案,並且運行ldconfig命令,通過ldconfig -p|grep XXX,來查看庫檔案是否已經被包括了
使得ld可以在程式運行時可動態載入庫檔案
注意二者必須同時滿足時候,調用程式才可以正常運行。
我開始以為在ld.so.conf.d/中添加路徑檔案並運行ldconfig之後就可以不用-L參數了,結果所以導致程式一直連結不通過,汗。。。。
參考文獻:
[1] Linux下共用庫路徑配置問題[ZZ|FY] http://blog.csdn.net/ldong2007/archive/2008/11/05/3227214.aspx