可移動的和可刪除的,其屬性在應用程序的模塊定義文件中指定。段在全局內存中分配空間,Windows鼓勵使用可移動的代碼段和數據段,這樣可以提高其內存利用效率。使用可刪除的代碼段可以進一步減小應用程序對內存的影響,如果代碼段是可刪除的,在必要時Windows將其刪除以滿足對全局內存的請求。被刪除的段由Windows監控,當應用程序利用該代碼段時,Windows自動地將它們重新裝入。
代碼段
代碼段是不超過64K字節的機器指令,它代表全部或部分應用程序指令。代碼段中的數據是隻讀的,對代碼段執行寫操作將引起通用保護(GP)錯誤。
每個應用程序都至少有一個代碼段,例如我們前麵幾章的例子都隻有一個代碼段。用戶也可以生成有多個代碼段的應用。實際上,多數Windows應用程序都有多個代碼段。通過使用多代碼段,用戶可以把任何給定代碼段的大小減少到完成某些任務所必須的幾條指令。這樣,可通過使某些段可刪除,來優化應用程序對內存的使用。
中模式和大模式的應用程序都使用多代碼段,這些應用程序的每一個段都有一個或幾個源文件。對於多個源文件,將它們分開各自編譯,為編譯過的代碼所屬的每個段命名,然後連接。段的屬性在模塊定義文件中定義,Windows使用SEGMENTS語句來完成此任務,如下麵的代碼定義了四個段的屬性:
用戶也可以在模塊定義文件中用語句為所有未顯式定義過的代碼段定義缺省屬性。例如,要將未列在SEGMENTS語句中的所有段定義為可刪除的,可用下麵的語句:
MOVEABLEDISCARDABLE。
數據段
每個應用程序都有一個數據段,數據段包含應用程序的堆棧、局部堆、靜態數據和全局數據。一個數據段的長度也不能超過64K。數據段可以是固定的或可移動的,但不能是可刪除的。如果數據段是可移動的,Windows在將控製轉向應用程序前自動為其加鎖,當應用程序分配全局內存,或試圖在局部堆中分配超過當前可分的內存時,可移動數據段可能被移動,因此在數據段中不要保留指向變量的長指針,當數據段移動時,此長指針將失效。
在模塊定義文件中用DATA語句定義數據段的屬性,屬性的缺省值為MOVEABLE和MULTIPLE。MULTIPLE屬性使Windows為應用程序的每一個實例拷貝一個應用程序數據段,這就是說每個應用程序實例中數據段的內容都是不同的。
內存管理程序示例Memory
應用程序Memory示例了部分內存管理,它是一個使用了可刪除代碼段的中模式Windows應用程序。Memory程序有四個C語言源程序,在模塊定義文件中顯示定義了四個代碼段,相應地模塊定義文件和makefile文件有地些修改,讀者可通過比較Memory程序和5.1.2節的例子來體會它們之間的不同。另外,讀者在編譯和連接應用程序Memory後,可用VisualC++提供的WindowsHeapWalker(HEAPWALK.EXE)來觀察Memory運行時的各個段。
動態連接庫
使用動態連接庫是Windows的一個很重要的特點,它使得多個Windows應用程序可以共享函數代碼、數據和硬件,這可以大大提高Windows內存的利用率。
動態連接庫是一個可執行模塊,它包含的函數可以由Windows應用程序調用執行,為應用程序提供服務。它和我們以前用的C函數庫相比,在功能上是很類似的,其主要區別是動態連接庫在運行是連接,C函數庫(靜態連接庫)是在生成可執行文件時由連接器(LINK)連接。靜態連接庫中的代碼在應用程序生成以後已經連接到應用程序模塊之中,但動態連接庫中的代碼隻有在應用程序要用到該代碼段時才動態調入DLL中的相應代碼。為了讓應用程序在執行時能夠調入DLL中正確的代碼,Windows提供了動態連接庫的引入庫。Windows在連接生成應用程序時,如果使用動態連接庫函數,連接器並不拷貝DLL中的任何代碼,它隻是將引入庫中指定所需函數在DLL中位置的信息拷貝在應用程序模塊中,當應用程序運行時,這些定位信息在可執行應用程序和動態連接庫之間建立動態連接。靜態庫、引入庫和動態庫之間的區別如表6.1所示。
DLL不能獨立執行,也不能使用消息循環。每個DLL都有一個入口點和一個出口點,具有自己的實例句柄、數據段和局部堆,但DLL沒有堆棧,它使用調用程序的堆棧。DLL也包括有.C文件,.H文件,.RC文件和.DEF文件,另外,在連接時一般要加入SDK庫中的LIBENTRY.OBJ文件。
本章節來源於𝑜𝑜𝑝.𝑡𝑤
創建動態連接庫
:件文個三有少至,庫接連態動建創要
;件文源言語C
;)FED.(件文義定塊模個一
。件文elifekam
。件文LLD成生,件文碼代源接連並譯編,)EKAMN(製機護維序程的tfosorciM行運以可就,後件文些這了有
件文源言語C建創
。出引句語STROPXE用中件文義定塊模的庫在且並,明聲RAF用前之用使庫或序程用應它其被在要數函個每,數函個多含包可庫接連態動,樣一序程用應C它其和
。PEW數函口出和niaMbiL數函口入LLD是就這,的需必所碼代源LLD是數函個兩有,中碼代源的麵上在
yrtnEbiL,寸尺的堆的義定件文義定塊模是eziSpaeHbc;值的器存寄)SD(段據數是geSataDw;柄句例實的庫接連態動是tsnIh中其。eniLdmCzspl和eziSpaeHbc,geSataDw,tnih:數參個四有niaMbiL。務任化始初些一成完來用要主,用調yrtnEbiL數函化始初動自LLD由它,點口入的LLD是數函niaMbiL