解析Linux靜態與動態鏈結庫的建立和使用

2021-05-24 00:16:46 字數 3970 閱讀 6599

首先由下面幾個函式:

strlen.h;strlen.c;strnlen.c;main.c

//strlen.h

標頭檔案int strnlen(char *pstr, unsigned long ulmaxlen);

int strlen(char *pstr);

//strlen.c

實現給定字串的長度

#include

#include

int strlen(char *pstr)

return ullength; }

//strnlen.c

獲取給定字串的長度,若輸入字串的長度大於指定的最大長度,則返回最大長度,否則返回字串的實際長度。

#include

#include

int strnlen(char *pstr, unsigned long ulmaxlen)

ullength = 0;

while(*pstr++ && ullength

return ullength; }

//main.c

#include"strlen.h"

#include

int main(int argc, char *argv)

第一種:生成靜態庫:

gcc –c strlen.c strnlen.c (

使用gcc

生成對應的目標檔案)

然後用ar

建立乙個名字為

libstr.a

的庫檔案,並把

strlen.o and strnlen.o

的內容插入到對應的庫檔案中。:

ar –rc libstr.a strlen.o strnlen.o(

命令成功後,對應的靜態庫

libstr.a

已經成功生成)

靜態庫的使用:

gcc –c –i./ main.c(

因為我的標頭檔案

strlen.h

就在當前目錄下,如果在別的目錄,比如在

/home/cc/strlen.h

。則這樣寫

gcc –c –l/home/cc main.c)

,現在就允許結果

第二種:生成動態庫

gcc –fpic –shared –o libstr.so strlen.c strnlen.c (-fpic

使輸出的物件模組是按照可重定位位址方式生成的)(

-shared

指定把對應的原始檔生成對應的動態鏈結庫檔案

libstr.so

檔案)(動態庫有兩種,乙個

.so結尾的是隱式呼叫的動態庫。呼叫

dlopen

函式的是顯式呼叫的動態庫)

隱式呼叫:

gcc –c –i./ main.c

gcc –o main1 –l./ main.o libstr.so

./main1

出現error while loading shared libraries: ***.so.0:cannot open shared object file: no such file or directory。

解決辦法:

庫檔案在連線和執行時被使用,其搜尋路徑在系統中進行設定的。一般

linux

系統把/lib

和/usr/lib

兩個目錄作為預設的庫搜尋路徑,所以使用這兩個目錄中的庫時不需要進行設定搜尋路徑即刻直接使用。對於處於預設庫之外的庫,需要將庫的位置(路徑)新增到庫的搜尋路徑之中。設定庫檔案的搜尋路徑有下列兩種方式,可任選一種:

a 在環境變數

ld_library_path

中指明庫的搜尋路徑。b 在

/etc/ld.so.conf

檔案中新增庫的搜尋路徑。

注:第一種方法我沒弄成功,看第二種。開啟

vi /etc/ld.so.conf

檔案,#include /etc/ld.so.conf.d/*.conf

(原文有的)換一行加上這個

/network_programing/02

(我的libstr.so

在這個目錄下面)儲存退出。然後執行

/sbin/ldconfig –v

。從新gcc

一次,執行

./main1

就出結果。

顯示呼叫:

//main3.c

#include

#include

int main(int argc, char *argv)

pszerr = dlerror();

if(pszerr != null)

pstrlenfun = dlsym(pdlhandle, "strlen");//

獲取函式的位址

pszerr = dlerror();

if(pszerr != null)

pstrnlenfun = dlsym(pdlhandle, "strnlen");

pszerr = dlerror();

if(pszerr != null)

printf("the string is:%s/n", str);

ullength = pstrlenfun(str);//

呼叫相關的函式

printf("the string length is:%d(use strlen)/n",(int)ullength);

ullength = pstrnlenfun(str, 10);

printf("the string length is:%d(use strnlen)/n", (int)ullength);

dlclose(pdlhandle);

return 0; }

gcc –o main3 –ldl main3.c

注意:用

gcc編譯對於的原始檔生成可執行檔案,

-ldl

選項,表示生成的物件模組需要使用共享庫。執行對應的檔案同樣可以得到正確的結果。

dlsym()

的函式原型是

void* dlsym(void* handle,const char* symbol)

該函式在檔案中。 handle是由dlopen開啟動態鏈結庫後返回的指標,symbol就是要求獲取的函式的名稱,函式返回值是void*,指向函式的位址,供呼叫使用。

dlopen

()功能:開啟乙個動態鏈結庫

包含標頭檔案:

#include

函式定義:  

void * dlopen( const char * pathname, int mode );

函式描述:

在dlopen

的()函式以指定模式開啟指定的

動態連線庫

檔案,並返回乙個控制代碼給呼叫程序。使用

dlclose

()來解除安裝開啟的庫。

mode

:分為這兩種

rtld_lazy

暫緩決定,等有需要時再解出符號

rtld_now

立即決定,返回前解除所有未決定的符號。

rtld_local

rtld_global

允許匯出符號

rtld_group

rtld_world

返回值

:

開啟錯誤返回

null

成功,返回庫引用

編譯時候要加入

-ldl (

指定dl庫)

const char *dlerror(void);

函式描述:當動態鏈結庫操作函式執行失敗時,dlerror可以返回出錯資訊,返回值為null時表示操作函式執行成功。

linux靜態鏈結庫與動態鏈結庫詳解

linux靜態鏈結庫與動態鏈結庫詳解 一順便說說了哦 通常情況下,對函式庫的鏈結是放在編譯時期 compile time 完成的.所有相關的物件檔案 object file 與牽涉到的函式庫 library 被鏈結合成乙個可執行檔案 executable file 程式在執行時,與函式庫再無瓜葛,因...

linux靜態鏈結庫與動態鏈結庫詳解

一順便說說了哦 通常情況下,對函式庫的鏈結是放在編譯時期 compile time 完成的.所有相關的物件檔案 object file 與牽涉到的函式庫 library 被鏈結合成乙個可執行檔案 executable file 程式在執行時,與函式庫再無瓜葛,因為所有需要的函式已拷貝到自己門下。所以...

動態鏈結庫與靜態鏈結庫

有人會想,動態鏈結這樣麻煩,為什麼還要用呢?這裡有乙個技術問題,對這個問題的解決直接導致了動態載入的需求。問題是有些dll只在某個windows版本中存在,或某個api只在某些windows版本中被加入指定的dll。當你使用靜態鏈結的.exe試圖在不支援的windows版本上執行時,系統會彈出系統對...