Windows 95/98下直接訪問實體記憶體 (轉)
Windows 95/98下直接訪問實體記憶體 (轉)[@more@] 95/98下直接訪問物理
在很多情況下,我們都有直接訪問實體記憶體的要求,如在實時高速資料採集中,
對I/O板上的器的訪問。但是,為了保證系統的性和穩定性,
並不提倡應用直接訪問資源, 因此,隨著作業系統的進步,導致了目前存在
的這樣一個不幸的事實: 以前在DOS下很容易實現的特定實體記憶體的讀寫操作,在Windows
下卻變得相當困難。
本文主要討論如何在Windows 95/98下實現實體記憶體的直接讀寫操作。為了論述清
楚這個問題,有必要敘述保護的定址方式以及W indows 95/98的記憶體管理方式。
Windows 95/98記憶體管理方式
Windows 95/98工作在32位保護模式下,保護模式與真實模式的根本區別在於定址方
式上的不同:儘管兩者對應的記憶體地址均為"段地址:偏移量"形式,但在保護模式下,
"段地址"代表的值已不再是真實模式中段的起始基準地址了;對於CS、DS、ES、SS寄存
器,在真實模式下,這些暫存器的值左移4位,再加上偏移量,即得到實體地址,而在保護
模式下,這些暫存器的值為"段選擇符",它實際上是一個查全域性描述符表(G DT)或局
部描述符表(LDT)的,據此在GDT或LDT找到對應的段描述符,從而獲得段的基址及
型別等資訊,再根據偏移量,才能得到線性地址。如果作業系統沒有采用分頁機制,
那麼得到的線性地址即為實體地址,否則,線性地址需要進一步經過分頁機制才能得
到實體地址。這就是保護模式下的"段頁式定址機制"。
Windows 95/98使用4GB的虛擬記憶體地址空間,應用程式訪問記憶體使用虛擬地址,從虛
擬地址到實體地址的轉換過程如圖1所示: 圖1 虛擬地址到實體地址的轉化過程
對於圖1中的分頁機制,Windows 95/98採用兩級頁表結構,如圖2 所示。圖2 採用的
分頁機制的兩級頁表結構
從圖2可知,線性地址被分割成頁目錄條目(PDE)、頁表條目(PTE) 、頁偏移地址(Off set)
三個部分。當建立一個新的WIN 32程式時,Wi ndows 95/98會為它分配一塊記憶體,並
建立它自己的頁目錄、頁表,頁目錄的地址也同時放入程式的現場資訊中。當計算一
個地址時,系統首先從控制暫存器CR3中讀出頁目錄所在的地址(該地址為實體地址,
並且是頁對齊的),然後根據PDE得到頁表所在的地址,再根據PTE得到包含了實際Code
或Data的頁幀, 最後根據Offset訪問頁幀中的特定單元。
常用記憶體段的段選擇符
從上述所介紹的Windows 95/98採用的分段、分頁機制可看出,要想在Windows 95/98
下直接訪問實體記憶體,關鍵是得到欲訪問實體記憶體所在的記憶體區域對應的段選擇符。
一般說來,要求直接訪問的實體記憶體都與真實模式下能夠定址的記憶體有關(即DOS能直
接訪問的1M實體記憶體)。在Windows 3.X中,Microso ft給出了DOS常用段的段選擇符,
如_000 0H(未公開),_B800H,_F000H( 已公開),等等,均可以在KERNEL中找到,應用
程式可以直接使用這些段選擇符,實現實體記憶體的直接訪問。而在Windows 95/98中,
卻不在任何文件中提供這些段的預定義,在KERNEL中也不提供相應的段選
擇符。但是,Windows 95 /98確實給DOS下的這些常用記憶體段定義了相應的段描述符。
透過SoftIce 3.02 for Win dows 95/98,我們得到了關於LDT的如下資訊:
...... :ldt
LDTbase=80003000 Limit=3FFF
……
1007 Data16 00000C90 0000FFFF 3 P RW
100F Data16 00000000 0000FFFF 3 P RW
1017 Data16 00000400 0000FFFF 3 P RW
101F Data16 000F0000 0000FFFF 3 P RW
1027 Data16 000A0000 0000FFFF 3 P RW
102F Data16 000B0000 0000FFFF 3 P RW
1037 Data16 000B8000 0000FFFF 3 P RW
103F Data16 000C0000 0000FFFF 3 P RW
1047 Data16 000D0000 0000FFFF 3 P RW
104F Data16 000E0000 0000FFFF 3 P RW
……
其中,每一行對應一個段描述符,第一欄為其段選擇符,第二欄為段描述符的型別,
第三欄為段的基地址(線性地址),第四欄為段的限長 ,第五欄為段描述符的特權級,
第六欄標誌對應段是否存在於記憶體中, 第七欄表示段的訪問。
可以看出,這些段的基地址與DOS下的常用記憶體段完全吻合,並且均為16位的資料段,
限長為64K(0XFFFF),供應用程式訪問,都存在於記憶體中,可讀寫。實踐證明,這些段
就是D OS的常用記憶體段,也就是說, 這裡的線性地址即為實體地址。因此,可以用這
些段選擇符對相應的實體記憶體進行訪問。
從程式執行的健壯性考慮,不應該直接應用上述段選擇符,而應該用GetThreadSelec
torEntry()得到欲訪問實體記憶體對應的段選擇符,該函式的原型定義為
BOOL GetThreadorEntry (
HANDLE hThread,
// handle of thread that contains selector
D dwSelector,
// number of selector value to look up
LPLDT_ENTRY lpSelectorEntry
// address of selector entry structure
);
其中,LDT_ENTRY的結構定義如下
typedef struct _LDT_ENTRY { // ldte
WORD LimitLow;
WORD BaseLow;
union {
struct {
BYTE BaseMid;
BYTE Flags1;
BYTE Flags2;
BYTE BaseHi;
} Bytes;
struct {
DWORD BaseMid : 8;
DWORD Type : 5;
DWORD Dpl : 2;
DWORD Pres : 1;
DWORD LimitHi : 4;
DWORD Sys : 1;
DWORD Reserved_0 : 1;
DWORD Default_Big : 1;
DWORD Granularity : 1;
DWORD BaseHi : 8;
} Bits;
} HighWord;
} LDT_ENTRY, *PLDT_ENTRY;
用下面的程式碼可以得到基地址為BASE_DESIRED,限長為0XFFFF的
記憶體段對應的段選擇符:
......
extern CLDTApp theApp;
WORD wSelector; // 記憶體段對應的段選擇符
LDT_ENTRY ldtEntry;
DWORD base, baseMid, baseHigh;
DWORD limit, limitHigh;
for ( WORD sel = 7; sel 非法段選擇符寫入段暫存器將會導
致通用保護錯誤(General Protection Faul t)。
下面的程式碼實現實體記憶體的讀/寫操作(段選擇符用上述方法得到):
void WriteMemory(WORD sel, DWORD dwOffset, const char * str, UINT length)
{
char cWrite;
for ( UINT i = 0; i 程式設計環境為Vis ual C++ 5.0。
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/10752043/viewspace-990722/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- [轉載] Java直接記憶體與堆記憶體Java記憶體
- VB也能訪問記憶體 (轉)記憶體
- 直接記憶體記憶體
- 直接記憶體和堆記憶體誰快記憶體
- Windows CE記憶體管理 (轉)Windows記憶體
- 記憶體訪問全過程記憶體
- Win95/98/NT 下對記憶體、埠、中斷的直接控制和讀寫 (轉)記憶體
- [轉貼]windows的虛擬記憶體Windows記憶體
- Java堆外直接記憶體回收Java記憶體
- 實體記憶體和虛擬記憶體記憶體
- Windows95下實體記憶體單元的可靠讀寫(透過選擇器方法)與上一篇不同 (轉)Windows記憶體
- 讀懂Windows虛擬記憶體問題Windows記憶體
- Keep小表到記憶體,提高訪問速度記憶體
- 記憶體管理篇——實體記憶體的管理記憶體
- 一個SMMU記憶體訪問異常的問題記憶體
- Windows記憶體管理-分段Windows記憶體
- 虛擬記憶體到實體記憶體(32位)記憶體
- 【Java基礎】實體記憶體&虛擬記憶體Java記憶體
- windows 32位的 Oracle 記憶體限制問題WindowsOracle記憶體
- 關於java記憶體訪問重排序的思考Java記憶體排序
- Windows記憶體機制解析(二)原始碼 (轉)Windows記憶體原始碼
- linux記憶體管理(一)實體記憶體的組織和記憶體分配Linux記憶體
- Oracle9i的實體記憶體管理(轉)Oracle記憶體
- Java直接(堆外)記憶體使用詳解Java記憶體
- 記憶體管理兩部曲之實體記憶體管理記憶體
- 【JVM之記憶體與垃圾回收篇】物件例項化記憶體佈局與訪問定位JVM記憶體物件
- windows95 mac最新版(windows95系統體驗軟體)支援armWindowsMac
- windows 備用記憶體清理Windows記憶體
- windows記憶體清理工具Windows記憶體
- Windows記憶體管理-分頁Windows記憶體
- Windows記憶體管理分析(一)Windows記憶體
- Windows記憶體管理分析(二)Windows記憶體
- 堆記憶體和棧記憶體詳解(轉載)記憶體
- ReFlex:讓遠端快閃記憶體訪問擁有本地訪問的效能Flex記憶體
- 01-0006 C++記憶體訪問越界 [問題整理]C++記憶體
- Oracle 記憶體顧問Oracle記憶體
- Windows中提高記憶體使用效率的絕技(轉)Windows記憶體
- JAVA記憶體管理 [轉]Java記憶體