本文這裡分析linux動態庫和windows動態庫通常採用的動態庫呼叫方法以及程式編制方式。動態庫的目的減少程式的大小,節省空間,提高效率,具有很高的靈活性。採用動態庫技術對於公升級軟體版本更加容易,動態庫裡面的函式不是執行程式本身的一部分,而是根據執行需要按需載入,其執行**可以同時在多個程式中共享。
windows動態庫技術
動態鏈結庫是實現windows應用程式共享資源、節省記憶體空間、提高使用效率的乙個重要技術手段。常見的動態庫包含外部函式和資源,也有一些動態庫只包含資源,如windows字型資源檔案,稱之為資源動態鏈結庫。通常動態庫以.dll,.drv、.fon等作為字尾。相應的windows靜態庫通常以.lib結尾,windows自己就將一些主要的系統功能以動態庫模組的形式實現。
windows動態庫在執行時被系統載入到程序的虛擬空間中,使用從呼叫程序的虛擬位址空間分配的記憶體,成為呼叫程序的一部分。dll也只能被該程序的執行緒所訪問。dll的控制代碼可以被呼叫程序使用;呼叫程序的控制代碼可以被dll使用。dll模組中包含各種匯出函式,用於向外界提供服務。dll可以有自己的資料段,但沒有自己的堆疊,使用與呼叫它的應用程式相同的堆疊模式;乙個dll在記憶體中只有乙個例項;dll實現了**封裝性;dll的編制與具體的程式語言及編譯器無關,可以通過dll來實現混合語言程式設計。dll函式中的**所建立的任何物件(包括變數)都歸呼叫它的執行緒或程序所有。
根據呼叫方式的不同,對動態庫的呼叫可分為靜態呼叫方式和動態呼叫方式。
(1)靜態呼叫,也稱為隱式呼叫,由編譯系統完成對dll的載入和應用程式結束時dll解除安裝的編碼(windows系統負責對dll呼叫次數的計數),呼叫方式簡單,能夠滿足通常的要求。通常採用的呼叫方式是把產生動態連線庫時產生的.lib檔案加入到應用程式的工程中,想使用dll中的函式時,只須在原始檔中宣告一下。 lib檔案包含了每乙個dll匯出函式的符號名和可選擇的標識號以及dll檔名,不含有實際的**。lib檔案包含的資訊進入到生成的應用程式中,被呼叫的dll檔案會在應用程式載入時同時載入在到記憶體中。
(2)動態呼叫,即顯式呼叫方式,是由程式設計者用api函式載入和解除安裝dll來達到呼叫dll的目的,比較複雜,但能更加有效地使用記憶體,是編制大型應用程式時的重要方式。在windows系統中,與動態庫呼叫有關的函式包括:
①loadlibrary(或mfc 的afxloadlibrary),裝載動態庫。
②getprocaddress,獲取要引入的函式,將符號名或標識號轉換為dll內部位址。
③freelibrary(或mfc的afxfreelibrary),釋放動態鏈結庫。
在windows中建立動態庫也非常方便和簡單。在visual c++中,可以建立不用mfc而直接用c語言寫的dll程式,也可以建立基於mfc類庫的dll程式。每乙個dll必須有乙個入口點,在vc++中,dllmain是乙個預設的入口函式。dllmain負責初始化(initialization)和結束(termination)工作。動態庫輸出函式也有兩種約定,分別是基於呼叫約定和名字修飾約定。dll程式定義的函式分為內部函式和匯出函式,動態庫匯出的函式供其它程式模組呼叫。通常可以有下面幾種方法匯出函式:
①採用模組定義檔案的export部分指定要輸入的函式或者變數。
②使用mfc提供的修飾符號_declspec(dllexport)。
③以命令列方式,採用/export命令列輸出有關函式。
在windows動態庫中,有時需要編寫模組定義檔案(.def),它是用於描述dll屬性的模組語句組成的文字檔案。
linux共享物件技術
在linux作業系統中,採用了很多共享物件技術(shared object),雖然它和windows裡的動態庫相對應,但它並不稱為動態庫。相應的共享物件檔案以.so作為字尾,為了方便,在本文中,對該概念不進行專門區分。linux系統的/lib以及標準圖形介面的/usr/x11r6/lib等目錄裡面,就有許多以so結尾的共享物件。同樣,在linux下,也有靜態函式庫這種呼叫方式,相應的字尾以.a結束。linux採用該共享物件技術以方便程式間共享,節省程式占有空間,增加程式的可擴充套件性和靈活性。linux還可以通過ld-preload變數讓開發人員可以使用自己的程式庫中的模組來替換系統模組。
同windows系統一樣,在linux中建立和使用動態庫是比較容易的事情,在編譯函式庫源程式時加上-shared選項即可,這樣所生成的執行程式就是動態鏈結庫。通常這樣的程式以so為字尾,在linux動態庫程式設計過程中,通常流程是編寫使用者的介面檔案,通常是.h檔案,編寫實際的函式檔案,以.c或.cpp為字尾,再編寫makefile檔案。對於較小的動態庫程式可以不用如此,但這樣設計使程式更加合理。
編譯生成動態連線庫後,進而可以在程式中進行呼叫。在linux中,可以採用多種呼叫方式,同windows的系統目錄(..\system32等)一樣,可以將動態庫檔案拷貝到/lib目錄或者在/lib目錄裡面建立符號連線,以便所有使用者使用。下面介紹linux呼叫動態庫經常使用的函式,但在使用動態庫時,源程式必須包含dlfcn.h標頭檔案,該檔案定義呼叫動態鏈結庫的函式的原型。
(1)_開啟動態鏈結庫:dlopen,函式原型void *dlopen (const char *filename, int flag);
dlopen用於開啟指定名字(filename)的動態鏈結庫,並返回操作控制代碼。
dlsym根據動態鏈結庫操作控制代碼(handle)與符號(symbol),返回符號對應的函式的執行**位址。
(3)關閉動態鏈結庫:dlclose,函式原型為: int dlclose (void *handle);
dlclose用於關閉指定控制代碼的動態鏈結庫,只有當此動態鏈結庫的使用計數為0時,才會真正被系統解除安裝。
(4)動態庫錯誤函式:dlerror,函式原型為: const char *dlerror(void); 當動態鏈結庫操作函式執行失敗時,dlerror可以返回出錯資訊,返回值為null時表示操作函式執行成功。
在取到函式執行位址後,就可以在動態庫的使用程式裡面根據動態庫提供的函式介面宣告呼叫動態庫裡面的函式。在編寫呼叫動態庫的程式的makefile檔案時,需要加入編譯選項-rdynamic和-ldl。
除了採用這種方式編寫和呼叫動態庫之外,linux作業系統也提供了一種更為方便的動態庫呼叫方式,也方便了其它程式呼叫,這種方式與windows系統的隱式鏈結類似。其動態庫命名方式為「lib*.so.*」。在這個命名方式中,第乙個*表示動態鏈結庫的庫名,第二個*通常表示該動態庫的版本號,也可以沒有版本號。在這種呼叫方式中,需要維護動態鏈結庫的配置檔案/etc/ld.so.conf來讓動態鏈結庫為系統所使用,通常將動態鏈結庫所在目錄名追加到動態鏈結庫配置檔案中。如具有x window視窗系統發行版該檔案中都具有/usr/x11r6/lib,它指向x window視窗系統的動態鏈結庫所在目錄。為了使動態鏈結庫能為系統所共享,還需執行動態鏈結庫的管理命令./sbin/ldconfig。在編譯所引用的動態庫時,可以在gcc採用 –l或-l選項或直接引用所需的動態鏈結庫方式進行編譯。在linux裡面,可以採用ldd命令來檢查程式依賴共享庫。
Linux靜態庫和動態庫的分析
庫有動態與靜態兩種,動態通常用.so為字尾,靜態用.a為字尾。例如 libhello.so libhello.a 為了在同一系統中使用不同版本的庫,可以在庫檔名後加上版本號為字尾,例如 libhello.so.1.0,由於程式連線預設以.so為檔案字尾名。所以為了使用這些庫,通常使用建立符號連線的方...
關於Linux靜態庫和動態庫的分析
庫有動態與靜態兩種,動態通常用.so 為字尾,靜態用 a為字尾。例如 libhello.so libhello.a 為了在同一系統中使用不同版本的庫,可以在庫檔名後加上版本號為字尾 例如 libhello.so.1.0,由於程式連線預設以 so為檔案字尾名。所以為了使用這些庫,通常使用建立符號連線的...
深入分析Windows和Linux動態庫應用異同
今天blog不好用了.借用寶地一下.深入分析windows和linux動態庫應用異同 摘要 動態鏈結庫技術實現和設計程式常用的技術,在windows和linux系統中都有動態庫的概念,採用動態庫可以有效的減少程式大小,節省空間,提高效率 增加程式的可擴充套件性,便於模組化管理。但不同作業系統的動態庫...