#參考:
[概述]本文是我在學習linux下動態鏈結庫的總結,主要內容為:為什麼要使用動態鏈結庫、動態鏈結庫的製作、使用。
0 為什麼要使用動態鏈結庫
linux下的庫檔案有:靜態庫和動態庫兩種。靜態庫檔案的製作和使用在前文中已簡要總結。linux系統中動態鏈結庫,類似於 windows中以.dll為字尾的檔案(dll即dynamic link library)。
靜態庫與動態庫的區別。如果程式是在編譯時載入庫檔案的,就是使用了靜態庫。如果是在執行時載入目標**,就成為動態庫。換句話說,如果是使用靜態庫,則靜態庫**在編譯時就拷貝到了程式的**段,程式的體積會膨脹。如果使用動態庫,則程式中只保留庫檔案的名字和函式名,在執行時去查詢庫檔案和函式體,程式的體積基本變化不大。
靜態庫的原則是「以空間換時間」,增加程式體積,減少執行時間;
動態庫則是「以時間換空間」,增加了執行時間,但減少了程式本身的體積。
1 動態鏈結庫的製作
在linux系統下,建立動態鏈結庫是件非常簡單的事情。只要在編譯函式庫源程式時加上-shared選項即可,這樣所生成的執行程式即為動態鏈結庫。從某種意義上來說,動態鏈結庫也是一種執行程式。按一般規則,動態庫的命名應為lib*.so.*。其中第乙個*為動態庫的名字,第二個*為版本號,比如libc.so.6。編譯生成動態庫的命令: gcc -o libmy.so -fpic -shared getdate.c gettime.c
下面製作動態庫的例子中有3個檔案: adatetime.h, getdate.c, gettime.c。adatetime.h為動態鏈結庫的標頭檔案; getdate.c和gettime.c分別實現getdate()和gettime()函式。
1.1 編寫動態庫標頭檔案adatetime.h,**如下:
1.2 編寫getdate.c和gettime.c,**如下:
1.3 編譯生成動態庫
(1) 編寫維護檔案makefile-lib,內容如下
注意: 每行維護**必須以tab(跳格鍵)開始,不是的話make時將出錯。
編寫維護檔案的目的,在於方便程式設計師維護程式,尤其是維護比較大的工程專案。
(2) 執行命令make -f makefile-lib, 則生成名為libmy.so的動態庫檔案。
1.4 共享動態庫檔案
/etc/ld.so.conf文件中,存放著可被linux共享的動態鏈結庫所在目錄的名字(系統目錄/lib,/usr/lib除外)。我們可以把自己製作的動態庫放到/lib或/usr/lib;也可以新建使用者自己的庫資料夾:/home/uname/lib,然後把此資料夾路徑寫入/etc/ld.so.conf中(並把自己的動態庫複製到該資料夾下)。
#ldconfig //重新整理快取文件/etc/lb.so.cache,使共享設定生效
然後就可以使用動態庫檔案libmy.so了。
2 動態庫檔案的使用
2.1 重要的dlfcn.h標頭檔案
linux下使用動態鏈結庫,源程式需要包含dlfcn.h標頭檔案,此檔案定義了呼叫動態鏈結庫的函式的原型。下面詳細說明一下這些函式。
2.1.1 dlerror
原型為: const char *dlerror(void);
當動態鏈結庫操作函式執行失敗時,dlerror可以返回出錯資訊,返回值為null時表示操作函式執行成功。
2.1.2 dlopen
原型為: void *dlopen (const char *filename, int flag);
dlopen用於開啟指定名字(filename)的動態鏈結庫,並返回操作控制代碼。
filename: 如果名字不以/開頭,則非絕對路徑名,將按下列先後順序查詢該檔案。
(1) 使用者環境變數中的ld_library值;
(2) 動態鏈結緩衝檔案/etc/ld.so.cache
(3) 目錄/lib,/usr/lib
flag表示在什麼時候解決未定義的符號(呼叫)。取值有兩個:
1) rtld_lazy : 表明在動態鏈結庫的函式**執行時解決。
2) rtld_now : 表明在dlopen返回前就解決所有未定義的符號,一旦未解決,dlopen將返回錯誤。
dlopen呼叫失敗時,將返回null值,否則返回的是操作控制代碼。
2.1.3 dlsym : 取函式執行位址
原型為: void *dlsym(void *handle, char *symbol);
dlsym根據動態鏈結庫操作控制代碼(handle)與符號(symbol),返回符號對應的函式的執行**位址。由此位址,可以帶引數執行相應的函式。
如程式**: void (*add)(int x,int y); /* 說明一下要呼叫的動態函式add */
add=dlsym("***.so","add"); /* 開啟***.so共享庫,取add函式位址 */
add(89,369); /* 帶兩個引數89和369呼叫add函式 */
2.1.4 dlclose : 關閉動態鏈結庫
原型為: int dlclose (void *handle);
dlclose用於關閉指定控制代碼的動態鏈結庫,只有當此動態鏈結庫的使用計數為0時,才會真正被系統解除安裝。
2.2 在程式中使用動態鏈結庫函式
2.2.0
動態庫的分為隱式呼叫和顯式
呼叫兩種呼叫方法。
隱式呼叫的使用使用方法和靜態庫的呼叫差不多,具體方法如下:
gcc -c -i/home/weil/inc main.c
gcc -o main1 -l/home/
weil
/lib main.o libmytime.so //這裡是*.so
在這種呼叫方式中,需要維護動態鏈結庫的 配置檔案/etc/ld.so.conf來讓動態鏈結庫為系統所使用,通常將動態鏈結庫所在目錄名追加到動態鏈結庫配置檔案中。否則在執行相關的可執行文 件的時候就會出現載入動態鏈結庫失敗的現象。
在編譯所引用的動態庫時,可以在gcc採用 –l或-l選項或直接引用所需的動態鏈結庫方式進行編譯。
在linux裡面,可以採用ldd命令來檢查程式依賴共享庫。
顯式呼叫:
gcc -o main -ldl main.c
用gcc編譯對應的原始檔生成可執行檔案,-ldl選項,表示生成的物件模組需要使用共享庫。
在示例程式ady.c中呼叫動態庫libmy.so中的getdate()和gettime()函式,用來顯式系統的當前時間。
2.2.1 編寫ady.c (本例中使用顯示呼叫的方法)
2.2.2 編寫維護檔案makefile
2.3 編譯、執行測試程式
#make
#./ady
可顯式系統當前日期、時間。
linux動態鏈結庫
在做完mini6410移植全攻略後,打算把自己的linux c筆記,貼出來和大家共享,有不對支援希望大家指出,謝謝!在上篇文章中,是對靜態鏈結庫的介紹,其實有了上面的介紹動態鏈結庫的製作就簡單了,這篇來製作動態鏈結庫 建立動態鏈結庫 cpp view plain copy print?gcc sha...
靜態鏈結庫與動態鏈結庫總結
1 在生成lib檔案的時候並不發生連線的過程,編譯器僅僅把obj檔案裝載為乙個lib檔案。例如 static1 int add int a,int b int sub int a,int b static2 int myadd int a,int b int mysub int a,int b 這個...
linux中的動態鏈結庫和靜態鏈結庫
什麼是庫?庫是寫好的現有的,成熟的,可以復用的 現實中每個程式都要依賴很多基礎的底層庫,不可能每個人的 都從零開始,因此庫的存在意義非同尋常。本質上來說庫是一種可執行 的二進位制形式,可以被作業系統載入記憶體執行。庫有兩種 靜態庫 a lib 和動態庫 so dll windows上對應的是.lib...