摘要:開發高速公路系統目的在于建立空間型的信息系統代替傳統的手工信息處理方法以提高高速公路運營管理的水平,由于系統所牽涉的面非常的寬廣,開發的難度很多,必須使用dll技術。該文即結合實際探討該系統的dll技術。
關鍵詞:dll技術;導出和導入函數;高速公路系統
中圖分類號:TP302文獻標識碼:A文章編號:1009-3044(2010)02-453-02
Highway System dll Technical Analysis
LIN Xue-yun
(Fuqing Branch of Fujian Normal University Mathematics and Computer Science Department, Fuqing 350300, China)
Abstract: The development of highway system, the aim of building space-based information system to replace the traditional manual information processing method to improve the highway operation and management level, because the system involved a very broad face, the difficulty of developing many techniques to use dll. This paper is to explore the light of the actual technology of the system dll.
Key words: dll technology; export and import functions; highway system
1 DLL技術的產生
比較大應用程序如高速公路系統都由很多模塊組成,這些模塊分別完成相對獨立的功能,它們彼此協作來完成整個軟件系統的工作。其中可能存在一些模塊的功能較為通用,在構造其它軟件系統時仍會被使用。在構造軟件系統時,如果將所有模塊的源代碼都靜態編譯到整個應用程序EXE文件中,會產生一些問題:一個缺點是增加了應用程序的大小,它會占用更多的磁盤空間,程序運行時也會消耗較大的內存空間,造成系統資源的浪費;另一個缺點是,在編寫大的EXE程序時,在每次修改重建時都必須調整編譯所有源代碼,增加了編譯過程的復雜性,也不利于階段性的單元測試。Windows系統平臺上提供了一種完全不同的較有效的編程和運行環境,可以將獨立的程序模塊創建為較小的DLL(Dynamic Linkable Libary了)文件,并可對它們單獨編譯和測試。在運行時,只有當EXE程序確實要調用這些DLL模塊的情況下,系統才會將它們裝載到內存空間中。這種方式不僅減少了EXE文件的大小和對內存空間的需求,而且使這些DLL模塊可以同時被多個應用程序使用。Microsoft Windows自己就將一些主要的系統功能以DLL模塊的形式實現。例如IE中的一些基本功能就是由DLL文件實現的,它可以被其它應用程序調用和集成。
2 dll的定義
一般來說,DLL是一種磁盤文件(通常帶有DLL擴展名),它由全局數據、服務函數和資源組成,在運行時被系統加載到進程的虛擬空間中,成為調用進程的一部分。如果與其它DLL之間沒有沖突,該文件通常映射到進程虛擬空間的同一地址上。DLL模塊中包含各種導出函數,用于向外界提供服務。Windows在加載DLL模塊時將進程函數調用與DLL文件的導出函數相匹配。
在Win32環境中,每個進程都復制了自己的讀/寫全局變量。如果想要與其它進程共享內存,必須使用內存映射文件或者聲明一個共享數據段。DLL模塊需要的堆棧內存都是從運行進程的堆棧中分配出來的。DLL現在越來越容易編寫。Win32已經大大簡化了其編程模式,并有許多來自Appwizard和MFC類庫的支持。
3 DLL編程技術
3.1 導出和導入函數的匹配
DLL文件中包含一個導出函數表。這些導出函數由它們的符號名和稱為標識號的整數與外界聯系起來。函數表中還包含了DLL中函數的地址。當應用程序加載DLL模塊時時,它并不知道調用函數的實際地址,但它知道函數的符號名和標識號。動態鏈接過程在加載的 DLL模塊時動態建立一個函數調用與函數地址的對應表。如果重新編譯和重建DLL文件,并不需要修改應用程序,除非你改變了導出函數的符號名和參數序列。
簡單的DLL文件只為應用程序提供導出函數,比較復雜的DLL文件除了提供導出函數以外,還調用其它DLL文件中的函數。這樣,一個特殊的DLL可以既有導入函數,又有導入函數。這并不是一個問題,因為動態鏈接過程可以處理交叉相關的情況。
但也可以在模塊定義(DEF)文件中列出導出函數,不過這樣做常常引起更多的麻煩。
僅有導入和導出聲明并不能使應用程序內部的函數調用鏈接到相應的DLL文件上。應用程序的項目必須為鏈接程序指定所需的輸入庫(LIB文件)。而且應用程序事實上必須至少包含一個對DLL函數的調用。
3.2 與DLL模塊建立鏈接
應用程序導入函數與DLL文件中的導出函數進行鏈接有兩種方式:隱式鏈接和顯式鏈接。所謂的隱式鏈接是指在應用程序中不需指明DLL文件的實際存儲路徑,程序員不需關心DLL文件的實際裝載。而顯式鏈接與此相反。
采用隱式鏈接方式,程序員在建立一個DLL文件時,鏈接程序會自動生成一個與之對應的LIB導入文件。該文件包含了每一個DLL導出函數的符號名和可選的標識號,但是并不含有實際的代碼。LIB文件作為DLL的替代文件被編譯到應用程序項目中。
當程序員通過靜態鏈接方式編譯生成應用程序時,應用程序中的調用函數與LIB文件中導出符號相匹配,這些符號或標識號進入到生成的EXE文件中。LIB文件中也包含了對應的DLL文件名(但不是完全的路徑名),鏈接程序將其存儲在EXE文件內部。
當應用程序運行過程中需要加載DLL文件。根據這些信息發現并加載DLL,然后通過符號名或標識號實現對DLL函數的動態鏈接。
顯式鏈接方式對于集成化的開發語言(例如VB)比較適合。有了顯式鏈接,程序員就不必再使用導入文件,而是直接調用LoadLibary函數,并指定DLL的路徑作為參數。應用程序在調用GetProcAddress函數時使用這一參數。GetProcAddress函數將符號名或標識號轉換為DLL內部的地址。
假設有一個導出如下函數的DLL文件:
在隱式鏈接方式中,所有被應用程序調用的DLL文件都會在應用程序EXE文件加載時被加載在到內存中;但如果采用顯式鏈接方式,程序員可以決定DLL文件何時加載或不加載。顯式鏈接在運行時決定加載哪個DLL文件。例如,可以將一個帶有字符串資源的DLL模塊以英語加載,而另一個以西班牙語加載。應用程序在用戶選擇了合適的語種后再加載與之對應的DLL文件。
使用符號名鏈接與標識號鏈接
在Winl6環境中,符號名鏈接效率較低,所以標識號鏈接是主要的鏈接方式。在Win32環境中,符號名鏈接的效率得到了改善。Microsoft現在推薦使用符號名鏈接。但在MFC庫中的DLL版本仍然采用的是標識號鏈接。一個典型的MFC程序可能會鏈接到數百個MFC DLL函數上。采用標識號鏈接的應用程序的EXE文件體相對較小,因為它不必包含導入函數的長字符串符號名。
3.3 編寫DUMain函數
DllMain函數是DLL模塊的默認入口點。當Windows加載DLL模塊時調用這一函數。系統首先調用全局對象的構造函數,然后調用全局函數DLLMain。DLLMain函數不僅在將DLL鏈接加載到進程時被調用,在DLL模塊與進程分離時(以及其它時候)也被調用。
如果程序員沒有為DLL模塊編寫一個DLLMain函數,系統會從其它運行庫中引入一個不做任何操作的缺省DLLMain函數版本。在單個線程啟動和終止時,DLLMain函數也被調用。
4 小結
本文是結合開發高速公路系統的各個模塊來探析dll技術的具體應用。由于系統規模龐大,所牽涉的面很廣,這只是其中的一個部分,作一個鳥瞰似的介紹。
參考文獻:
[1] 林康紅,唐海峰,奉玲,等.動態鏈接庫DLL在虛擬儀器中的應用[J].自動化與儀表,2002(5).
[2] 羅錦,孟晨,蘇振中.動態鏈接庫技術在虛擬儀器系統構建中的應用[J].電子技術,2002(9).
[3] 劉寶祥.談談動態鏈接與動態鏈接庫[J].科技信息:學術版,2006,(7).
[4] 孫濱,周楊,郭曉東.動態鏈接庫技術及其應用[J].電腦編程技巧與維護,2009(15).