电脑知识|欧美黑人一区二区三区|软件|欧美黑人一级爽快片淫片高清|系统|欧美黑人狂野猛交老妇|数据库|服务器|编程开发|网络运营|知识问答|技术教程文章 - 好吧啦网

您的位置:首頁技術(shù)文章
文章詳情頁

《Undocumented Windows 2000 Secrets》翻譯 --- 第四章(2)

瀏覽:90日期:2023-08-27 14:16:44

第四章 探索 Windows 2000 的內(nèi)存管理機(jī)制

翻譯: Kendiv( fcczj@263.net )

更新: Sunday, February 14, 2005

聲明:轉(zhuǎn)載請注明出處,并保證文章的完整性,本人保留譯文的所有權(quán)利。

數(shù)據(jù)結(jié)構(gòu)

本章隨后的示例代碼的某些部分將涉及底層的內(nèi)存管理機(jī)制,在前面我們已快速瀏覽了該機(jī)制內(nèi)部的大致輪廓。為了方便,我用 C 語言定義了幾個數(shù)據(jù)結(jié)構(gòu)。這是因?yàn)?i386 CPU 內(nèi)部的很多數(shù)據(jù)項(xiàng)需要使用一個二進(jìn)制位或一組二進(jìn)制位,而 C 的位域( bit-fIElds )唾手可得。位域可以很有效的訪問一個大的數(shù)據(jù)中的一個位或從中提取一組連續(xù)的位。微軟的 Visual C/C++ 可以產(chǎn)生非常棒的代碼來完成位域的操作。 列表 4-2 是一系列 CPU 數(shù)據(jù)類型定義的一部分,該列表包含如下的內(nèi)容:

l X86_REGISTER 這是一個基本的無符號 32 位整數(shù)類型,該類型可描述多個 CPU 寄存器。這包括:通用的、索引、指針、控制、調(diào)試和測試寄存器。

l X86_SELECTOR 代表一個 16 位的段選擇器,如 CS 、 DS 、 ES 、 FS 、 GS 和 SS 。在 4-1 4-2 中,選擇器可描述 48 位邏輯地址的高 8 位,或作為描述符表的索引。為了計算的方便, 16 位選擇器的值被擴(kuò)展到 32 位,不過高 16 位被標(biāo)識為“保留”。注意, X86_SELECTOR 結(jié)構(gòu)實(shí)際是兩個結(jié)構(gòu)的聯(lián)合( union )。第一個指定了選擇器的值,該值占用一個 16 位的 Word ,其名字為 wValue ,第二個采用了位域。 RPL 域指定了請求的特權(quán)級,在 Windows 2000 上其值或者為 0 (內(nèi)核模式)或者為 3 (用戶模式)。 TI 位用來選擇 GDT 或 LDT 。

l X86_DESCRIPTOR 定義了由選擇器指向的頁表項(xiàng)的格式。這是一個 64 位的數(shù)值,由于歷史演化,該結(jié)構(gòu)比較讓人費(fèi)解。線性基地址定義了與其相關(guān)的段的起始位置,它們分散在三個位域中: Base1 、 Base2 和 Base3 , Base1 是作用最小的部分。段的界限指定了段的大小, The segment limit specifying the segment size minus one is divided into the pair Limitl and Limit2, with the former representing the least significant half. 剩余的位域存放不同的段屬性( cf. Intel 1999c, pp.3-11 )。例如, G 位域定義了段的粒度。如果為零,段的限制按字節(jié)指定;否則,限制值為 4KB 的倍數(shù)。像 X86_SELECTOR 一樣, X86_DESCRIPTOR 結(jié)構(gòu)由一個 union 組成,以允許按不同的方式解釋它的值。如果你必須復(fù)制描述符(在忽略其內(nèi)部情況下)那么 dValueLow 和 dValueHigh 成員將會很有幫助。

l X86_GATE 該結(jié)構(gòu)看起來有些像 X86_DESCRIPTOR 。事實(shí)上,這兩個結(jié)構(gòu)是相關(guān)的: X86_DESCRIPTRO 是一個 GDT 項(xiàng),并描述了一個段的內(nèi)存屬性, X86_GATE 代表中斷描述符表( IDT )中的一項(xiàng),并描述了中斷例程的內(nèi)存屬性。 IDT 可以包含任務(wù)、中斷和陷阱門(不! Bill Gates 并沒有存儲在 IDT 中! 哈哈)。 X86_GATE 結(jié)構(gòu)可匹配上述三種類型,并通過 Type 位域來進(jìn)行區(qū)分。 Type 5 表示這是一個任務(wù)門; Type 6 和 14 為中斷門; Type 7 和 15 為陷阱門。 Type 中最重要的位是用來描述門的位數(shù)的位:該位若為 0 則表示是 16 位門;其余情況表示 32 位門。

l X86_TABLE 是一個巧妙的結(jié)構(gòu),該結(jié)構(gòu)用來讀取 GDTR 或 IDTR 的當(dāng)前值,分別通過匯編指令 SGDT (存儲 GDT 寄存器)和 SIDT (存儲 IDT 寄存器)來實(shí)現(xiàn)( cf. Intel 1999b, pp.3-636 )。這兩個指令需要一個 48 位的內(nèi)存操作數(shù),在該操作數(shù)中存放限制值和基地址值。通過在結(jié)構(gòu)體中增加一個 DWORD 來對齊 32 位的基地址, X86_TABLE 以一個 16 位的啞元成員 wReserved 開始。根據(jù)是否使用了 SGDT 或 SIDT 指令,其基地址將被解釋為一個描述符指針或一個門指針,就像 PX86_DESCRIPTOR 和 PX86_GATE 中的 union 所暗示的那樣。最后的 wLimit 成員在這兩種類型的表中的意義均相同。

譯注:

列表 4-2 中的這些結(jié)構(gòu)定義可以在隨書光盤的 srccommonincludew2k_spy.h 中找到。

typedef DWORD X86_REGISTER, *PX86_REGISTER, **PPX86_REGISTER;

// -----------------------------------------------------------------

typedef struct _X86_SELECTOR

{

union

{

struct

{

WORD wValue; // packed value

WORD wReserved;

};

struct

{

unsigned RPL : 2; // requested privilege level

unsigned TI : 1; // table indicator: 0=gdt, 1=ldt

unsigned Index : 13; // index into descriptor table

unsigned Reserved : 16;

};

};

}

X86_SELECTOR, *PX86_SELECTOR, **PPX86_SELECTOR;

#define X86_SELECTOR_ sizeof (X86_SELECTOR)

// -----------------------------------------------------------------

typedef struct _X86_DESCRIPTOR

{

union

{

struct

{

DWORD dValueLow; // packed value

DWORD dValueHigh;

};

struct

{

unsigned Limit1 : 16; // bits 15..00

unsigned Base1 : 16; // bits 15..00

unsigned Base2 : 8; // bits 23..16

unsigned Type : 4; // segment type

unsigned S : 1; // type (0=system, 1=code/data)

unsigned DPL : 2; // descriptor privilege level

unsigned P : 1; // segment present

unsigned Limit2 : 4; // bits 19..16

unsigned AVL : 1; // available to programmer

unsigned Reserved : 1;

unsigned DB : 1; // 0=16-bit, 1=32-bit

unsigned G : 1; // granularity (1=4KB)

unsigned Base3 : 8; // bits 31..24

};

};

}

X86_DESCRIPTOR, *PX86_DESCRIPTOR, **PPX86_DESCRIPTOR;

#define X86_DESCRIPTOR_ sizeof (X86_DESCRIPTOR)

// -----------------------------------------------------------------

typedef struct _X86_GATE

{

union

{

struct

{

DWORD dValueLow; // packed value

DWORD dValueHigh;

};

struct

{

unsigned Offset1 : 16; // bits 15..00

unsigned Selector : 16; // segment selector

unsigned Parameters : 5; // parameters

unsigned Reserved : 3;

unsigned Type : 4; // gate type and size

unsigned S : 1; // always 0

unsigned DPL : 2; // descriptor privilege level

unsigned P : 1; // segment present

unsigned Offset2 : 16; // bits 31..16

};

};

}

X86_GATE, *PX86_GATE, **PPX86_GATE;

#define X86_GATE_ sizeof (X86_GATE)

// -----------------------------------------------------------------

typedef struct _X86_TABLE

{

WORD wReserved; // force 32-bit alignment

WORD wLimit; // table limit

union

{

PX86_DESCRIPTOR pDescriptors; // used by sgdt instruction

PX86_GATE pGates; // used by sidt instruction

};

}

X86_TABLE, *PX86_TABLE, **PPX86_TABLE;

#define X86_TABLE_ sizeof (X86_TABLE)

列表 4-2. i386 的寄存器、選擇器、描述符、門和表

接下來的一組與 i386 內(nèi)存管理相關(guān)的結(jié)構(gòu),它們收錄在 列表 4-3 中,這些結(jié)構(gòu)包括:與請求式分頁相關(guān)的結(jié)構(gòu)和 4-3 4-4 給出的幾個成員。

l X86_PDBR 該結(jié)構(gòu)對應(yīng) CPU 的 CR3 寄存器,即眾所周知的頁目錄基地址寄存器( PDBR )。其高 20 位為 PFN ,即 4KB 物理頁數(shù)組的索引。 PFN=0 對應(yīng)物理地址 0x00000000 , PFN=1 為 0x00001000 ,依此類推。 20 個位足夠轉(zhuǎn)換整個 4GB 地址空間。 PDBR 中的 PFN 是物理頁的索引,用來控制整個頁目錄。 PFN 中剩余的位大多數(shù)都被保留,但 3 號位例外,它用來控制頁一級的 write-through ( page-level write-through, PWT ), 4 號位如果為 1 ,則禁止頁一級的高速緩沖。

l X86_PDE_4M X86_PDE_4K 是頁目錄項(xiàng)( PDE )的兩個可選方案,用來選擇 4MB 頁或者 4KB 的頁。一個頁目錄中最多包含 1024 個 PDE 。 PFN 是頁幀號,它指向下一級的頁。對于一個 4MB 的 PDE ,其 PFN 位域僅有 10 個位的寬度,可尋址一個 4MB 的數(shù)據(jù)頁。 4KB 的 PDE 擁有 20 位的 PFN ,可指向一個頁表,由頁表最終選擇一個數(shù)據(jù)頁。剩余的位用來定義多種屬性。這些屬性中最有趣的是“頁大小”位 PS ,用于控制頁的大小( 0=4KB , 1=4MB )和“存在”位 P ,標(biāo)識下屬的數(shù)據(jù)頁( 4MB 模式)或頁表( 4KB 模式)是否存在于物理內(nèi)存中。

X86_PTE_4K 定義了頁表項(xiàng)(屬于一個頁表)的內(nèi)部結(jié)構(gòu)。和頁目錄類似,一個頁表可擁有 1024 個項(xiàng)。 X86_PTE_4K 和 X86_PDE_4K 的不同之處為:前者沒有 PS 位,這根本不需要,因?yàn)轫摰拇笮】隙ㄊ?4KB 。需要注意的是,沒有所謂的 4MB 的 PTE ,因?yàn)椴捎?4MB 頁的內(nèi)存模式不需要頁表這一中間層。

X86_PNPE 代表一個“不存在的頁”項(xiàng)( page-not-present entry, PNPE ),也就是說,一個 PDE 或 PTE 中的 P 位為 0 。如 Intel 的手冊所說的,保留的第 31 位是“對操作系統(tǒng)或執(zhí)行體( executive )均可用”( Intel 1999c,pp. 3-28 )。如果一個線性地址映射到了一個 PNPE ,這意味著這個地址或者還未使用或者它所指向的頁已經(jīng)被置換到了頁面文件中。 Windows 2000 使用 PNPE 保留的第 31 位來存儲頁的信息。有關(guān)頁信息的結(jié)構(gòu)沒有文檔記載,不過它類似于名為 PageFile 的第 10 位,如 列表 4-3 所示,如果設(shè)置了該位,則表示頁已被置換出物理內(nèi)存。在這種情況下, Reserved1 和 Reserved2 位域?qū)到y(tǒng)在頁面文件中定位該頁的信息,因此,當(dāng)需要訪問該頁時,可很快的將其換回物理內(nèi)存。

X86_PE 該結(jié)構(gòu)是為了方便使用而加入的。它僅包含一個 union ,該 union 包括頁項(xiàng)所有可能的狀態(tài),此處的頁項(xiàng)是指: PDBR 的內(nèi)容、所有 4MB 和 4KB 的 PDE 、 PTE ,以及所有的 PNPE 。

typedef struct _X86_PDBR // page-Directory base register (cr3)

{

union

{

struct

{

DWORD dValue; // packed value

};

struct

{

unsigned Reserved1 : 3;

unsigned PWT : 1; // page-level write-through

unsigned PCD : 1; // page-level cache disabled

unsigned Reserved2 : 7;

unsigned PFN : 20; // page-frame number

};

};

}

X86_PDBR, *PX86_PDBR, **PPX86_PDBR;

#define X86_PDBR_ sizeof (X86_PDBR)

// -----------------------------------------------------------------

typedef struct _X86_PDE_4M // page-directory entry (4-MB page)

{

union

{

struct

{

DWORD dValue; // packed value

};

struct

{

unsigned P : 1; // present (1 = present)

unsigned RW : 1; // read/write

unsigned US : 1; // user/supervisor

unsigned PWT : 1; // page-level write-through

unsigned PCD : 1; // page-level cache disabled

unsigned A : 1; // accessed

unsigned D : 1; // dirty

unsigned PS : 1; // page size (1 = 4-MB page)

unsigned G : 1; // global page

unsigned Available : 3; // available to programmer

unsigned Reserved : 10;

unsigned PFN : 10; // page-frame number

};

};

}

X86_PDE_4M, *PX86_PDE_4M, **PPX86_PDE_4M;

#define X86_PDE_4M_ sizeof (X86_PDE_4M)

// -----------------------------------------------------------------

typedef struct _X86_PDE_4K // page-directory entry (4-KB page)

{

union

{

struct

{

DWORD dValue; // packed value

};

struct

{

unsigned P : 1; // present (1 = present)

unsigned RW : 1; // read/write

unsigned US : 1; // user/supervisor

unsigned PWT : 1; // page-level write-through

unsigned PCD : 1; // page-level cache disabled

unsigned A : 1; // accessed

unsigned Reserved : 1; // dirty

unsigned PS : 1; // page size (0 = 4-KB page)

unsigned G : 1; // global page

unsigned Available : 3; // available to programmer

unsigned PFN : 20; // page-frame number

};

};

}

X86_PDE_4K, *PX86_PDE_4K, **PPX86_PDE_4K;

#define X86_PDE_4K_ sizeof (X86_PDE_4K)

// -----------------------------------------------------------------

typedef struct _X86_PTE_4K // page-table entry (4-KB page)

{

union

{

struct

{

DWORD dValue; // packed value

};

struct

{

unsigned P : 1; // present (1 = present)

unsigned RW : 1; // read/write

unsigned US : 1; // user/supervisor

unsigned PWT : 1; // page-level write-through

unsigned PCD : 1; // page-level cache disabled

unsigned A : 1; // accessed

unsigned D : 1; // dirty

unsigned Reserved : 1;

unsigned G : 1; // global page

unsigned Available : 3; // available to programmer

unsigned PFN : 20; // page-frame number

};

};

}

X86_PTE_4K, *PX86_PTE_4K, **PPX86_PTE_4K;

#define X86_PTE_4K_ sizeof (X86_PTE_4K)

// -----------------------------------------------------------------

typedef struct _X86_PNPE // page not present entry

{

union

{

struct

{

DWORD dValue; // packed value

};

struct

{

unsigned P : 1; // present (0 = not present)

unsigned Reserved1 : 9;

unsigned PageFile : 1; // page swapped to pagefile

unsigned Reserved2 : 21;

};

};

}

X86_PNPE, *PX86_PNPE, **PPX86_PNPE;

#define X86_PNPE_ sizeof (X86_PNPE)

// -----------------------------------------------------------------

typedef struct _X86_PE // general page entry

{

union

{

DWORD dValue; // packed value

X86_PDBR pdbr; // page-directory Base Register

X86_PDE_4M pde4M; // page-directory entry (4-MB page)

X86_PDE_4K pde4K; // page-directory entry (4-KB page)

X86_PTE_4K pte4K; // page-table entry (4-KB page)

X86_PNPE pnpe; // page not present entry

};

}

X86_PE, *PX86_PE, **PPX86_PE;

#define X86_PE_ sizeof (X86_PE)

列表 4-3. i386 的 PDBR 、 PDE 、 PTE 和 PNPE

列表 4-4 中,我增加了線性地址的結(jié)構(gòu)化表示。這些結(jié)構(gòu)是 4-3 4-4 中的“線性地址”的正式形式。

l X86_LINEAR_4M 該結(jié)構(gòu)是指向 4MB 數(shù)據(jù)頁的線性地址的正式形式,如 4-4 所示。頁目錄索引( PDI )是一個頁目錄的索引,頁目錄地址由 PDBR 給出,使用 PDI 可選擇頁目錄中的一個 PDE 。 22 位的 Offset 成員指向一個目標(biāo)地址,此目標(biāo)地址對應(yīng) 4MB 的物理頁。

l X86_LINEAR_4K 是一個 4KB 線性地址類型的變量,如 4-3 所示。該結(jié)構(gòu)由三個位域組成:和 4MB 地址類似,高 10 位為 PDI ,用來選擇一個 PDE ;頁表索引 PTI 的任務(wù)與 PDI 相似,指向由 PDE (該 PDE 由前面的 PDI 指定)確定的頁表中的一個 PTE ;剩余的 12 個位是在 4KB 物理頁中的偏移量。

l X86_LINEAR 是另一個為使用方便而加入的結(jié)構(gòu)。該結(jié)構(gòu)只是簡單的將 X86_LINEAR_4K 和 X86_LINEAR_4M 聯(lián)合為一個數(shù)據(jù)類型。詳見 列表 4-4

typedef struct _X86_LINEAR_4M // linear address (4-MB page)

{

union

{

struct

{

PVOID pAddress; // packed address

};

struct

{

unsigned Offset : 22; // offset into page

unsigned PDI : 10; // page-directory index

};

};

}

X86_LINEAR_4M, *PX86_LINEAR_4M, **PPX86_LINEAR_4M;

#define X86_LINEAR_4M_ sizeof (X86_LINEAR_4M)

// -----------------------------------------------------------------

typedef struct _X86_LINEAR_4K // linear address (4-KB page)

{

union

{

struct

{

PVOID pAddress; // packed address

};

struct

{

unsigned Offset : 12; // offset into page

unsigned PTI : 10; // page-table index

unsigned PDI : 10; // page-directory index

};

};

}

X86_LINEAR_4K, *PX86_LINEAR_4K, **PPX86_LINEAR_4K;

#define X86_LINEAR_4K_ sizeof (X86_LINEAR_4K)

// -----------------------------------------------------------------

typedef struct _X86_LINEAR // general linear address

{

union

{

PVOID pAddress; // packed address

X86_LINEAR_4M linear4M; // linear address (4-MB page)

X86_LINEAR_4K linear4K; // linear address (4-KB page)

};

}

X86_LINEAR, *PX86_LINEAR, **PPX86_LINEAR;

#define X86_LINEAR_ sizeof (X86_LINEAR)

列表 4-4. i386 的線性地址

宏和常量

列表 4-5 給出的定義是對 列表 4-2 列表 4-4 所示結(jié)構(gòu)的補(bǔ)充,讓我們可以更容易的和 i386 內(nèi)存管理一起工作。 列表 4-5 的定義可以分為三大組。第一組用于控制線性地址:

1. X86_PAGE_MASK X86_PDI_MASK X86_PTI_MASK 都是位掩碼( bit mask ),用來選擇線性地址中的某一部分。它們都基于常量: PAGE_SHIFT (12) 、 PDI-SHIFT (22) 和 PTI-SHIFT (12) ,這些常量定義于 Windows 2000 DDK 的頭文件 ntddk.h 中。 X86_PAGE_MASK 等價于 0xFFFFF000 ,可有效的屏蔽 4KB 線性地址( X86_LINEAR_4K )中的偏移量部分。 X86_PDI_MASK 等價于 0xFFC00000 ,顯然這可從線性地址中提取高 10 位的 PDI 。 X86_PTI_MASK 等價于 0x003FF0000 ,用于屏蔽線性地址中除 PTI 外的所有位。

2. X86_PAGE() X86_PDI() X86_PTI() 使用上面的常量來計算給定線性地址的頁索引、 PDI 和 PTI 。 X86_PAGE() 一般用來從 Windows 2000 的 PTE 數(shù)組(該數(shù)組首地址為: 0xC0000000 )中讀取一個 PTE 。 X86_PDI() 和 X86_PTI() 只是針對給定的指針,簡單的使用 X86_PDI_MASK 或 X86_PTI_MASK ,并將得到的索引移動到最右邊。

3. X86_OFFSET_4M() X86_OFFSET_4K() 分別從 4MB 或 4KB 線性地址中提取偏移量部分。

4. X86_PAGE_4M X86_PAGE_4K 根據(jù) DDK 中的常量 PDI_SHIFT 和 PTI_SHIFT 來計算 4MB 和 4KB 頁的大小。 X86_PAGE_4M=4,194,304 , X86_PAGE_4K=4,096 。注意, X86_PAGE_4K 等價于 DDK 常量 PAGE_SIZE ,該常量也定義于 ntddk.h 中。

5. X86_PAGES_4M X86_PAGES_4K 分別表示 4GB 地址空間中可容納的 4MB 或 4KB 頁的總數(shù)。 X86_PAGES_4M 等價于 1,024 , X86_PAGES_4K 等價于 1,048,576 。

#define X86_PAGE_MASK (0 - (1 << PAGE_SHIFT))

#define X86_PAGE(_p) (((DWORD) (_p) & X86_PAGE_MASK) >> PAGE_SHIFT)

#define X86_PDI_MASK (0 - (1 << PDI_SHIFT))

#define X86_PDI(_p) (((DWORD) (_p) & X86_PDI_MASK) >> PDI_SHIFT)

#define X86_PTI_MASK ((0 - (1 << PTI_SHIFT)) & ~X86_PDI_MASK)

#define X86_PTI(_p) (((DWORD) (_p) & X86_PTI_MASK) >> PTI_SHIFT)

#define X86_OFFSET(_p,_m) ((DWORD_PTR) (_p) & ~(_m))

#define X86_OFFSET_4M(_p) X86_OFFSET (_p, X86_PDI_MASK)

#define X86_OFFSET_4K(_p) X86_OFFSET (_p, X86_PDI_MASK|X86_PTI_MASK)

#define X86_PAGE_4M (1 << PDI_SHIFT)

#define X86_PAGE_4K (1 << PTI_SHIFT)

#define X86_PAGES_4M (1 << (32 - PDI_SHIFT))

#define X86_PAGES_4K (1 << (32 - PTI_SHIFT))

// -----------------------------------------------------------------

#define X86_PAGES 0xC0000000

#define X86_PTE_ARRAY ((PX86_PE) X86_PAGES)

#define X86_PDE_ARRAY (X86_PTE_ARRAY + (X86_PAGES >> PTI_SHIFT))

// -----------------------------------------------------------------

#define X86_SEGMENT_OTHER 0

#define X86_SEGMENT_CS 1

#define X86_SEGMENT_DS 2

#define X86_SEGMENT_ES 3

#define X86_SEGMENT_FS 4

#define X86_SEGMENT_GS 5

#define X86_SEGMENT_SS 6

#define X86_SEGMENT_TSS 7

// -----------------------------------------------------------------

#define X86_SELECTOR_RPL 0x0003

#define X86_SELECTOR_TI 0x0004

#define X86_SELECTOR_INDEX 0xFFF8

#define X86_SELECTOR_SHIFT 3

#define X86_SELECTOR_LIMIT (X86_SELECTOR_INDEX >>

X86_SELECTOR_SHIFT)

// -----------------------------------------------------------------

#define X86_DESCRIPTOR_SYS_TSS16A 0x1

#define X86_DESCRIPTOR_SYS_LDT 0x2

#define X86_DESCRIPTOR_SYS_TSS16B 0x3

#define X86_DESCRIPTOR_SYS_CALL16 0x4

#define X86_DESCRIPTOR_SYS_TASK 0x5

#define X86_DESCRIPTOR_SYS_INT16 0x6

#define X86_DESCRIPTOR_SYS_TRAP16 0x7

#define X86_DESCRIPTOR_SYS_TSS32A 0x9

#define X86_DESCRIPTOR_SYS_TSS32B 0xB

#define X86_DESCRIPTOR_SYS_CALL32 0xC

#define X86_DESCRIPTOR_SYS_INT32 0xE

#define X86_DESCRIPTOR_SYS_TRAP32 0xF

// -----------------------------------------------------------------

#define X86_DESCRIPTOR_APP_ACCESSED 0x1

#define X86_DESCRIPTOR_APP_READ_WRITE 0x2

#define X86_DESCRIPTOR_APP_EXECUTE_READ 0x2

#define X86_DESCRIPTOR_APP_EXPAND_DOWN 0x4

#define X86_DESCRIPTOR_APP_CONFORMING 0x4

#define X86_DESCRIPTOR_APP_CODE 0x8

列表 4-5. 附加的 i386 內(nèi)存管理相關(guān)定義

第二組宏和常量與 Windows 2000 的 PDE 、 PTE 數(shù)組有關(guān)。和其他幾個系統(tǒng)地址不同,這些數(shù)組的基地址并沒有在系統(tǒng)啟動時作為一個全局變量出現(xiàn),而是被定義成了一個常量。可以通過反編譯內(nèi)存管理 API 函數(shù): MmGetPhysicalAddress() 和 MmIsAddressValid() 來證明,在這些函數(shù)里,這些地址都以“魔術(shù)數(shù)字”的形式出現(xiàn)。這些常量并沒有包括在 DDK 頭文件中,不過 列表 4-5 展示了如何定義它們。

l X86_PAGES 是一個硬編碼的地址和指針(指向 0xC0000000 ), 0xC0000000 是 Windows 2000 的 PTE 數(shù)組開始的地方。

X86_PTE_ARRAY 等價于 X86_PAGES ,但是被轉(zhuǎn)型為 PX86_PE ,也就是說,指向一個 X86_PE 類型的數(shù)組, X86_PE 定義于列表 4-2 。

X86_PDE_ARRAY 是一個巧妙的定義,它通過 PTE 數(shù)組的位置來計算 PDE 數(shù)組的基地址,這需要用到 PTI_SHIFT 常量。將線性地址映射為 PTE 地址的通用格式為:(( LinearAdress >> 12 ) *4 ) +0xC0000000 ,線性地址 0xC0000000 轉(zhuǎn)換后的地址為頁目錄的基地址。

列表 4-5 的最后兩部分包括選擇器和特殊類型的描述符,以及對 列表 4-2 的補(bǔ)充。

l X86_SELECTOR_RPL 、 X86_SELECTOR_TI 和 X86_SELECTOR_INDEX 都是位掩碼,分別對應(yīng) X86_SELECTOR 結(jié)構(gòu)中的 RPL 、 TI 和 Index 成員。

l X86_SELECTOR_SHIFT 是一個右移因子,用來使選擇器的 Index 的數(shù)值向右對齊。

l X86_SELECTOR_LIMIT 定義了選擇器可使用的最大索引值,該限制為 8,191 。這個值確定了描述符表的最大尺寸。每個選擇器索引均指向一個描述符,每個描述符包含 64 個位(即 8 個字節(jié))。所以,描述符表的最大尺寸為: 8,192*8=64KB 。

l X86_DESCRIPTOR_SYS_* 是一組常量,用于定義系統(tǒng)描述符類型。如果描述符的 S 位被設(shè)為 0 ,那么描述的 Type 成員將采用這一組類型中的某一個。請參考 列表 4-2 中的 X86_DESCRIPTOR 的定義。系統(tǒng)描述符類型在 Intel 手冊中有詳細(xì)介紹( Intel 1999c, pp. 3-15f ), 4-1 給出了所有可用的系統(tǒng)描述符類型。

列表 4-5 中的 X86_DESCRIPTOR_APP_* 常量也可用于定義描述符的 Type 成員,前提是描述符的 S 位不為 0 。此時,該應(yīng)用程序描述符可能需要引用一個代碼或數(shù)據(jù)段。因?yàn)閼?yīng)用程序描述符類型的屬性受 Type 域的第四個位影響,所以 X86_DESCRIPTOR_APP_* 常量被定義為單位掩碼( single-bit mask ),這樣一些位就可針對數(shù)據(jù)和代碼段有不同的解釋。

l X86_DESCRIPTOR_APP_ACCESSED 如果一個段可以被訪問,則采用

l X86_DESCRIPTOR_APP_READ_WRITE 決定一個數(shù)據(jù)段是否允許只讀或讀 / 寫訪問。

l X86_DESCRIPTOR_APP_CONFORMATING 說明一個代碼段是否相匹配。也就是說,它是否可以被以被弱特權(quán)代碼( less privileged code )調(diào)用(參考 Intel 1999c,pp. 4-13ff )。

l X86_DESCRIPTOR_APP_CODE 用來區(qū)別代碼段和數(shù)據(jù)段。注意,堆棧屬于數(shù)據(jù)段的范疇,而且必須總是可寫的。

稍后,當(dāng)下一章中的 Memory Spy 程序開始運(yùn)行時,我們將重溫系統(tǒng)描述符。 4-1 算是 i386 內(nèi)存管理的一個簡短總結(jié)。有關(guān)本話題的更多內(nèi)容,請參考 Intel Pentium 手冊( Intel 1999a , 1999b , 1999c )。

表 4-1. 系統(tǒng)描述符類型

X86_DESCRIPTOR_SYS_TSS16A

0x1

16 位任務(wù)狀態(tài)段(可用)

X86_DESCRIPTOR_SYS_LDT

0x2

本地描述符表( LDT )

X86_DESCRIPTOR_SYS_TSS16B

0x3

16 位任務(wù)狀態(tài)段(繁忙)

X86_DESCRIPTOR_SYS_CALL16

0x4

16 位調(diào)用門

X86_DESCRIPTOR_SYS_TASK

0x5

任務(wù)門

X86_DESCRIPTOR_SYS_INT16

0x6

16 位中斷門

X86_DESCRIPTOR_SYS_TRAP16

0x7

16 位陷阱門

X86_DESCRIPTOR_SYS_TSS32A

0x9

32 位任務(wù)狀態(tài)段(可用)

X86_DESCRIPTOR_SYS_TSS32B

0xB

32 位任務(wù)狀態(tài)段(繁忙)

X86_DESCRIPTOR_SYS_CALL32

0xC

32 位調(diào)用門

X86_DESCRIPTOR_SYS_INT32

0xE

32 位中斷門

X86_DESCRIPTOR_SYS_TRAP32

0XF

32 位陷阱門

標(biāo)簽: Windows系統(tǒng)
主站蜘蛛池模板: 桁架楼承板-钢筋桁架楼承板-江苏众力达钢筋楼承板厂 | 科普仪器菏泽市教育教学仪器总厂 | 专注氟塑料泵_衬氟泵_磁力泵_卧龙泵阀_化工泵专业品牌 - 梭川泵阀 | POS机办理_个人POS机免费领取 - 银联POS机申请首页 | 电子巡更系统-巡检管理系统-智能巡检【金万码】 | 天坛家具官网 | 不锈钢/气体/液体玻璃转子流量计(防腐,选型,规格)-常州天晟热工仪表有限公司【官网】 | 网站优化公司_SEO优化_北京关键词百度快速排名-智恒博网络 | 润滑脂-高温润滑脂-轴承润滑脂-食品级润滑油-索科润滑油脂厂家 | 台湾阳明固态继电器-奥托尼克斯光电传感器-接近开关-温控器-光纤传感器-编码器一级代理商江苏用之宜电气 | 砂石生产线_石料生产线设备_制砂生产线设备价格_生产厂家-河南中誉鼎力智能装备有限公司 | 内窥镜-工业内窥镜厂家【上海修远仪器仪表有限公司】 | 壹作文_中小学生优秀满分作文大全| 印刷人才网 印刷、包装、造纸,中国80%的印刷企业人才招聘选印刷人才网! | 3dmax渲染-效果图渲染-影视动画渲染-北京快渲科技有限公司 | 天津市能谱科技有限公司-专业的红外光谱仪_红外测油仪_紫外测油仪_红外制样附件_傅里叶红外光谱技术生产服务厂商 | 99文库_实习生实用的范文资料文库站| 上海小程序开发-小程序制作-上海小程序定制开发公司-微信商城小程序-上海咏熠 | 西装定制/做厂家/公司_西装订做/制价格/费用-北京圣达信西装 | 东莞市超赞电子科技有限公司 全系列直插/贴片铝电解电容,电解电容,电容器 | 江苏密集柜_电动_手动_移动_盛隆柜业江苏档案密集柜厂家 | 澳威全屋定制官网|极简衣柜十大品牌|衣柜加盟代理|全屋定制招商 百度爱采购运营研究社社群-店铺托管-爱采购代运营-良言多米网络公司 | 数控车床-立式加工中心-多功能机床-小型车床-山东临沂金星机床有限公司 | 不干胶标签,不干胶标签纸_厂家-山东同力胶粘制品| 天津云仓-天津仓储物流-天津云仓一件代发-顺东云仓 | 逗网红-抖音网红-快手网红-各大平台网红物品导航 | PSI渗透压仪,TPS酸度计,美国CHAI PCR仪,渗透压仪厂家_价格,微生物快速检测仪-华泰和合(北京)商贸有限公司 | 光纤测温-荧光光纤测温系统-福州华光天锐光电科技有限公司 | 临沂招聘网_人才市场_招聘信息_求职招聘找工作请认准【马头商标】 | 智慧水务|智慧供排水利信息化|水厂软硬件系统-上海敢创 | 高空重型升降平台_高空液压举升平台_高空作业平台_移动式升降机-河南华鹰机械设备有限公司 | 头条搜索极速版下载安装免费新版,头条搜索极速版邀请码怎么填写? - 欧远全 | 屏蔽服(500kv-超高压-特高压-电磁)-徐吉电气| 上海质量认证办理中心| 除甲醛公司-甲醛检测-广西雅居环境科技有限公司 | 标准光源箱|对色灯箱|色差仪|光泽度仪|涂层测厚仪_HRC大品牌生产厂家 | 加气混凝土砌块设备,轻质砖设备,蒸养砖设备,新型墙体设备-河南省杜甫机械制造有限公司 | 胶原检测试剂盒,弹性蛋白检测试剂盒,类克ELISA试剂盒,阿达木单抗ELISA试剂盒-北京群晓科苑生物技术有限公司 | elisa试剂盒价格-酶联免疫试剂盒-猪elisa试剂盒-上海恒远生物科技有限公司 | 诺冠气动元件,诺冠电磁阀,海隆防爆阀,norgren气缸-山东锦隆自动化科技有限公司 | 葡萄酒灌装机-食用油灌装机-液体肥灌装设备厂家_青州惠联灌装机械 |