色综合图-色综合图片-色综合图片二区150p-色综合图区-玖玖国产精品视频-玖玖香蕉视频

您的位置:首頁技術文章
文章詳情頁

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

瀏覽:92日期:2023-08-27 14:18:45

第四章 探索 Windows 2000 的內存管理機制

翻譯: Kendiv( fcczj@263.ne t)

更新: Sunday, February 13, 2005

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

內存管理對于操作系統來說是非常重要的。本章將全面的縱覽 Windows 2000 的內存管理機制以及 4GB 線性地址空間的結構。針對此部分內容,將解釋 Intel i386 CPU 家族的虛擬內存尋址及其分頁能力,重點將在于 Windows 2000 的內核是如何使用它們的。為了幫助我們對內存的探索,本章提供了一對程序:一個內核模式的驅動程序,該驅動用來收集系統相關的信息,另一個是用戶模式的應用程序,該程序將通過設備 I/O 控制來查詢來自驅動程序的數據,并在控制臺窗口中進行顯示。在剩余的章節中將重復使用“ Spy Driver ”模塊來完成其他幾個非常有趣的任務(這些任務都需要在內核模式下執行代碼)。請堅持閱讀完本章的第一部分,因為它將直接面對 CPU 硬件。不過,我仍然希望你不要跳過它,因為虛擬內存管理是一個非常令人興奮的話題,理解它是如何工作的,將幫助你洞察復雜操作系統(如 Windows 2000 )采用的機制。

Intel i386 內存管理機制

Windows 2000 內核大量使用 Intel i386 CPU 系列提供的保護模式下的虛擬內存管理機制。為了更好的理解 Windows 2000 如何管理它的主內存,最低限度的熟悉 i386 CPU 的架構某些特點就顯得尤為重要。 Windows 2000 是針對 Pentium 以上 CPU 設計的。不過,這些新的處理器采用的內存管理模型仍源自針對 80386 CPU 的設計,不過當然會加入了一些重要的增強。因此,微軟通常標注 Windows NT 和 Windows 2000 的版本為 Intel 處理器“ i386 ”或者“ x86 ”。不要對這些感到困惑,不管你在本書的什么地方遇到 86 或 386 ,請記住,這只是表示特定的 CPU 架構,而不是特定的處理器版本。

基本的內存布局

Windows 2000 為應用程序和系統代碼提供了非常簡單的內存布局。由 32 位的 Intel CPU 提供的 4GB 虛擬內存空間被分割為相等的兩部分。低于 0x80000000 的內存地址由用戶模式下的模塊使用,這包括 Win32 子系統,剩余的 2GB 保留給了系統內核。 Windows 2000 Advanced Server 還支持通常稱為 4GT RAM Tuning 的另一種內存模型,該模型隨 Windows NT 4.0 Server 的企業版引入。該模型可提供 3GB 的用戶地址空間,另 1GB 保留給內核,通過在 boot.ini 中添加 /3GB 選項來啟用該模型。

Windows 2000 Advanced Server 和 DataCenter 支持稱為:物理地址擴展( Physical Address Extension, PAE )的內存選項,通過在 boot.ini 中加入 /PAE 就可允許這種內存方式。該選項采用了某些 Intel CPU 的特性(如, Pentium Pro 處理器)以允許大于 4GB 的物理內存映射到 32 位的地址空間上。在本章中,我將忽略這種特殊的設置。你可閱讀微軟的基本知識文章 Q171793 (微軟 2000c )、 Intel 的 Pentium 手冊( Intel 1999a,1999b,1999c )以及 Windows 2000 DDK 文檔(微軟 2000f )來獲取更多此方面的信息。

內存分段和請求式分頁

在深入 i386 架構的技術細節之前,想讓我們回到 1978 年,那一年 Intel 發布了 PC 處理器之母: 8086 。我想將討論限制到這個有重大意義的里程碑上。如果你打算知道更多,閱讀 Robert L. 的 80486 程序員參考( Hummel 1992 )將是一個很棒的開始。現在看來這有些過時了,因為它沒有涵蓋 Pentium 處理器家族的新特性;不過,該參考手冊中仍保留了大量 i386 架構的基本信息。盡管 8086 能夠訪問 1MB RAM 的地址空間,但應用程序還是無法“看到”整個的物理地址空間,這是因為 CPU 寄存器的地址僅有 16 位。這就意味著應用程序可訪問的連續線性地址空間僅有 64KB ,但是通過 16 位段寄存器的幫助,這個 64KB 大小的內存窗口就可以在整個物理空間中上下移動, 64KB 邏輯空間中的線性地址作為偏移量和基地址(由 16 位的段寄存器給處)相加,從而構成有效的 20 位地址。這種古老的內存模型仍然被最新的 Pentium CPU 支持,它被稱為:實地址模式,通常叫做:實模式。

80286 CPU 引入了另一種模式,稱為:受保護的虛擬地址模式,或者簡單的稱之為:保護模式。該模式提供的內存模型中使用的物理地址不再是簡單的將線性地址和段基址相加。為了保持與 8086 和 80186 的向后兼容, 80286 仍然使用段寄存器,但是在切換到保護模式后,它們將不再包含物理段的地址。替代的是,它們提供了一個選擇器( selector ),該選擇器由一個描述符表的索引構成。描述符表中的每一項都定義了一個 24 位的物理基址,允許訪問 16MB RAM ,在當時這是一個很不可思議的數量。不過, 80286 仍然是 16 位 CPU ,因此線性地址空間仍然被限制在 64KB 。

1985 年的 80386 CPU 突破了這一限制。該芯片最終砍斷了 16 位尋址的鎖鏈,將線性地址空間推到了 4GB ,并在引入 32 位線性地址的同時保留了基本的選擇器 / 描述符架構。幸運的是, 80286 的描述符結構中還有一些剩余的位可以拿來使用。從 16 位遷移到 32 位地址后, CPU 的數據寄存器的大小也相應的增加了兩倍,并同時增加了一個新的強大的尋址模型。真正的 32 位的數據和地址為程序員帶了實際的便利。事實上,在微軟的 Windows 平臺真正完全支持 32 位模型是在好幾年之后。 Windows NT 的第一個版本在 1993 年 7 月 26 日發布,實現了真正意義上的 Win32 API 。但是 Windows 3.x 程序員仍然要處理由獨立的代碼和數據段構成的 64KB 內存片, Windows NT 提供了平坦的 4GB 地址空間,在那兒可以使用簡單的 32 位指針來尋址所有的代碼和數據,而不需要分段。在內部,當然,分段仍然在起作用,就像我在前面提及的那樣。不過管理段的所有責任都被移給了操作系統。

80386 的另一個新特性是在硬件上支持分頁,確切的來說是:請求式分頁的虛擬內存。這種技術允許一個不同于 RAM 的存儲介質 ---- 硬盤來為內存提供支持,例如,在允許分頁時, CPU 通過將最近最少訪問的內存數據置換到備份存儲器中,從而為新的數據騰出空間,這樣就能訪問比可用物理內存更大的內存空間。理論上來說,可以使用此種方式訪問 4GB 的連續線性地址空間,提供的備份介質必須足夠的大 --- 即 使只安裝了非常少的物理內存。當然,分頁并不是訪問內存的最快方式,最好還是能提供盡可能多的物理內存。但是,這是處理大量數據的最好辦法,即使這些數據 超過了可用物理內存。例如,圖形和數據庫程序都需要一大塊工作內存,如果沒有分頁機制的話,其中的某些程序就無法在低檔的 PC 系統中運行。

80386 分頁的模式是將內存劃分為 4KB 或 4MB 大小的頁。操作系統的設計者可以在二者之間自由的選擇,也可混合使用這兩個大小的頁面。稍后,我會介紹 Windows 2000 采用的混合大小方案:由操作系統使用 4MB 的頁面,而 4KB 頁面由剩余的代碼和數據使用。這些頁面由分層結構的頁表樹管理,該頁表樹記錄當前位于物理內存中的頁,同時還記錄了每個頁是否實際的位于物理內存中。如果指定頁已被置換到了硬盤上,而某些模塊觸及了位于這些頁中的地址, CPU 就會產生一個缺頁中斷(這與外圍硬件產生的中斷類似)。接下來,位于操作系統內核中的缺頁中斷處理例程會試圖將該頁再次調入物理內存,這可能需要將另一塊內存中的數據寫入硬盤以騰出空間。通常,系統采用最近最少( LRU )算法來確定哪個頁可以被置換出去。現在可以很清楚地看到為什么有時將這個過程稱為 ---- 請求式分頁( demand paging ):即,由軟件提出請求,然后根據操作系統和應用程序使用的內存的統計數據,將物理內存中的數據移動到后備存儲設備中。

由頁表提供的間接尋址方式蘊含著很有趣的兩件事。第一,程序所使用的地址和 CPU 使用的物理地址總線上的地址之間并沒有預設的關系。如果你知道你的程序所使用的數據結構位于某一地址,如, 0x00140000 ,你可能仍然不想知道任何有關這些數據的物理地址的信息,除非你要檢查頁表樹( page-table tree )。 這需要操作系統來決定這些地址之間的映射關系。甚至當前有效的地址轉換都是無法預測的,部分的來看,這是分頁機制所固有的隨機性導致的。幸運的是,在大多 數應用程序中,并不需要有關物理地址的知識。不過,對于開發硬件驅動程序的人員來說還是需要某些這方面的知識。分頁的另一個隱晦之處是:地址空間并不必須 是連續的。實際上,根據頁表的內容, 4GB 的空間可以包含大量的“空洞”,這些“空洞”既沒有映射到物理內存也沒有映射到后備存儲器中。如果一個應用程序試圖讀取或寫入這樣的一個地址,它將立即被系統中止掉。稍后,我會詳細的說明 Windows 2000 是如何將可用內存擴展到 4GB 地址空間的。

80486 和 Pentium CPU 使用的分段和分頁機制與 80386 很相似,但一些特殊的尋址特性除外,如 Pentium Pro 采用的物理地址擴展( Physical Address Extension, PAE )機制。隨同更高的時鐘頻率一起, Pentium CPU 的另一特性就是其采用的雙重指令流水線,這一特性允許它在同一時刻執行兩個操作(只要這兩個指令不互相依賴)。例如,如果指令 A 修改一個寄存器的值,而與其相鄰的指令 B 需要這個修改后的值來進行計算,在 A 完成之前, B 將無法執行。但是如果指令 B 使用另一個寄存器, CPU 就可同時執行這兩個指令。 Pentium 系列 CPU 采用的多種優化方式為編譯器的優化提供了廣闊的空間。如果你對這方面的話題很感興趣,請參考 Rick 的《 Inner Loops 》( Booth 1997 )。

在 i386 的內存管理中,有三類地址非常有名,它們的術語 --- 邏輯、線性和物理地址出現在 Intel 的系統編程手冊( Intel 1999c )。

1. 邏輯地址 :這是內存地址的精確描述,通常表示為 16 進制: xxxx:YYYYYYYY ,這里 xxxx 為 selector ,而 YYYYYYYY 是針對 selector 所選擇的段地址的線性偏移量。除了指定 xxxx 的具體數值外,還可使用具體的段寄存器的名字來替代之,如 CS (代碼段), DS (數據段), ES (擴展段), FS (附加數據段 #1 ), GS (附加數據段 #2 )和 SS (堆棧段)。這些符號都來自舊的“段 : 偏移量”風格,在 8086 實模式下使用此種方式來指定“ far pointers ”(遠指針)。

2. 線性地址 :大多數應用程序和內核驅動程序都忽略虛擬地址。它們只對虛擬地址的偏移量部分感興趣,而這一部分通常稱為線性地址。此種類型的地址假定了一種默認的分段模型,這種模型由 CPU 的當前段寄存器確定。 Windows 2000 使用 flat segmentation (平滑段),此時 CS 、 DS 、 ES 和 SS 寄存器都指向相同的線性地址空間;因此,程序可以認為所有的代碼、數據和堆棧指針都可安全的相互轉化。例如,在任何時候,堆棧中的一個地址都可以轉化為一個數據指針,而不需要關心相應段寄存器的值。

3. 物理地址 :僅當 CPU 工作于分頁模式時,此種類型的地址才會變得非常“有趣”。本質上,一個物理地址是 CPU 插腳上可測量的電壓。操作系統通過設立頁表將線性地址映射為物理地址。 Windows 2000 所用頁表的布局的某些屬性,對于調試軟件開發人員非常有用,本章稍后將討論之。

虛擬地址和線性地址的差別多少有些人為的痕跡,在一些文檔中會交替的使用這兩個詞。我會盡力保證使用這一術語的一致性。特別需要注意的是, Windows 2000 假定物理地址有 64 位寬。而 Intel i386 系統通常只有一個 32 位的地址總線。不過,某些 Pentium 系統支持大于 4GB 的物理內存。例如,使用 PAE 模式的 Pentium Pro CPU ,這種 CPU 可以將物理地址擴展到 36 位,這樣就可訪問多大 64GB 的物理內存( Intel 1999c )。因此, Windows 2000 的 API 函數通常使用數據類型 PHYSICAL_ADDRESS 來表示物理地址, PHYSICAL_ADDRESS 實際是 LARGE_INTEGER 結構的別名,如 列表 4-1 所示。這兩種類型都定義在 DDK 頭文件 ntdef.h 中。 LARGE_INTEGER 實際上是 64 位有符號整數的結構化表示,它可以被解釋為一對 32 位數( LowPart 和 HighPart )或一個完整的 64 位數( QuadPart )。 LONGLONG 類型等價于 Visual C/C++ 的原生類型 __int64 ,該類型的無符號表示叫做 ULONGLONG 或 DWordLONG ,它們都依賴基本的無符號類型 __int64 。

圖 4-1 給出了 i386 內存的分段模型,同時說明了邏輯地址和線性地址的關系。為了更清晰些,我將描述符表( descriptor table )和段( segment )畫的比較小。實際上, 32 位的操作系統通常采用 4-2 所示的分段方案,這就是所謂的平滑內存模型( flat memory model ),它采用一個 4GB 大小的段。這種方案的不足是,描述符表變成了段的一部分,從而可以被有足夠權限的代碼訪問到。

typedef LARGE_INTEGER PHYSICAL_ADDRESS, *PPHYSICAL_ADDRESS;

typedef union _LARGE_INTEGER

{

struct

{

ULONG LowPart;

LONG HighPart;

};

LONGLONG QuadPart;

} LARGE_INTEGER, *PLARGE_INTEGER;

列表 4-1. PHYSICAL_ADDRESS 和 LARGE_INTEGER 結構的定義

圖 4-1. i386 的內存分段

圖 4-2 給出的內存模型被 Windows 2000 作為標準的代碼、數據和堆棧段,這意味著,所有的邏輯地址將包括 CS 、 DS 、 ES 和 SS 段寄存器。 FS 和 GS 的處理方式有所不同。 Windows 2000 并不使用 GS 寄存器,而 FS 寄存器被專門用來保存位于線性地址空間中的系統數據區域的基地址。因此, FS 的基地址遠大于 0 ,其大小不會超過 4GB 。有趣的是, Windows 2000 為用戶模式和內核模式分別維護兩個不同的 FS 段。稍后我們將詳細討論這一問題。

圖 4-2. 平滑的 4GB 內存段

4-1 4-2 中,邏輯地址的 selector 指向描述符表,該描述符表由名為 GDTR 的寄存器指定。這是 CPU 的全局描述符表寄存器,該寄存器可由操作系統設置為任何適當的線性地址。 GDT (全局描述符表)的第一項是保留的,該項對應的 selector 叫做“ null segment selector ”。 Windows 2000 將其 GDT 保存在 0x80036000 。 GDT 可容納多達 8,19264 位的條目,即其最大值為 64KB 。 Windows 2000 僅使用開始的 128 個項,并將 GDT 的大小限制為 1,024 字節。隨 GDT 一起, i386 CPU 還提供了一個本地描述符表( Local Descriptor Table , LDT )和一個中斷描述符表( Interrupt Descriptor Table , IDT ),這兩個表的起始地址分別保存在 LDTR 和 IDTR 這兩個寄存器中。 GDTR 和 IDTR 的值是唯一的, CPU 執行的每個任務都采用相同的值,而 LDTR 的值則是任務相關的, LDTR 可容納一個 16 位的 selector 。

圖 4-3 示范了復雜的線性地址與物理地址的轉換機制,如果在 4KB 分頁模式下,并允許請求式分頁, i386 的內存管理單元就會采用此種轉換機制。圖中左上角的頁目錄基址寄存器( Page-Directory Base Register , PDBR )包含頁目錄的物理地址。 PDBR 由 i386 的 CR3 寄存器保存。僅用該寄存器的高 20 位來尋址。因此,頁目錄也是以頁為邊界的。 PDBR 的剩余位作為標志位或保留以便將來擴展使用。頁目錄占用一個完整的 4KB 頁,由包含 1024 個頁目錄項( Page-Directory Entry )的數組構成,每個頁目錄項均為 32 位。和 PDBR 類似,每個 PDE 被劃分為一個 20 位的頁幀計數器( Page-Frame Number , PFN )和一個標志數組。 PFN 用來尋址頁表。每個頁表都是按頁對齊的,包含 1024 個頁表項( Page-Table Entry , PTE )。每個 PTE 的高 20 位作為一個指針指向一個 4KB 的數據頁。通過將線性地址分為三段來實現地址轉換:高 10 位用來選擇一個 PDE (屬于頁目錄),接下來的 10 個位選擇前面所選的 PDE 中的某個 PTE ,最后剩下的 12 個位用來指定在數據頁中的偏移量,該數據頁由前面所選的 PTE 確定。

圖 4-3. 兩層間接模型(采用 4KB 頁)

在 4MB 分頁模式下,事情就變得很簡單了,這是因為消除了一個間接層,如 4-4 所示。此時, PDBR 仍然指向頁目錄,但僅使用了每個 PDE 的高 10 位,這是因為目標地址采用 4MB 對齊。因為沒有使用頁表,這個地址同樣也是 4MB 數據頁的基地址。所以,此時的線性地址只包含兩個部分: 10 個位用來選擇 PDE ,其余的 22 位作為偏移量。 4MB 內存方案的開銷沒有 4KB 那么大,這是因為僅頁目錄需要附加的內存。這 1024 個 PDE 中的每個都可尋址一個 4MB 頁。這足夠覆蓋整個 4GB 地址空間了。所以, 4MB 分頁的優勢就是可以降低內存管理的開銷,但結果就是尋址粒度較大。

4KB 和 4MB 分頁模型各有優缺點。幸運的是,操作系統的設計人員不必非要在二者之中選擇一個,可以混合使用這兩種模型。例如, Windows 2000 在內存范圍 0x80000000 --- 0x9FFFFFFF 使用 4MB 大小的頁,內核模塊 hal.dll 和 ntoskrnl.exe 均被加載到該地址范圍內。剩余的線性地址采用 4KB 頁來管理。 Intel 大力推薦采用這種混合設計,以改進系統性能,這也因為 4KB 和 4MB 的頁項( Page Entry )都會被高速緩存到不同的轉換后備緩沖區( Translation Lookaside Buffers , TLBs )中,該 TLB 位于 i386 CPU 內部( Intel 1999c , pp.3-22f )。操作系統的內核通常比較大,而且需要常駐內存,因此,如果將它們保存在多個 4KB 頁中將會永久性的耗盡寶貴的 TLB 空間。

圖 4-4. 一層間接模型(采用 4MB 頁)

注意,地址轉換的所有步驟都在物理內存中進行。 PDBR 和所有的 PDE 、 PTE 包含的都是物理地址指針。在 4-3 4-4 中可找到的線性地址位于左下角,該線性地址將轉化為物理頁中的偏移量。另一方面,應用程序卻必須使用線性地址,它們對物理地址一無所知。不過,通過將頁目錄和其下屬的所有頁表映射到線性地址空間可以填補這一不足。在 Windows 2000 和 Windows NT 4.0 中,在線性地址范圍 0xC0000000----0xC03FFFFF 可訪問所有的 PDE 和 PTE ,這是一個采用 4MB 頁的線性內存區域。可以簡單的通過線性地址的高 20 位來查找與其相關聯的 PTE ,這個高 20 位作為 32 位 PTE 數組的索引, PTE 數組起始于 0xC0000000 。例如,地址 0x00000000 表示的 PTE 位于 0xC0000000 。假定有一線性地址 0x80000000 ,通過將該地址右移 12 位,可得到 0x80000 (即該地址的高 20 位),因為每個 PTE 占用 4 個字節,所以目標 PTE 的地址為: 0xC0000000+ ( 4*0x80000 ) =0xC0200000 。這樣的結果看起來很有趣,線性地址將 4GB 地址空間劃分為相等的兩部分,又映射為一個 PTE 的地址,從而將 PTE 數組也劃分為了相等的兩部分。

現在,讓我們更進一步,通過 PTE 自身來計算數據項在 PTE 數組中的地址。常規的映射公式為:(( LinearAddress >> 12 ) *4 ) +0xC0000000 。 LinearAddress 取值范圍為: 0xC0000000----0xC0300000 。位于線性地址 0xC0300000 的數據項指向 PTE 數組在物理內存中的起始位置。現在回去看一下 4-3 ,開始于地址 0xC0300000 的 1024 個數據項肯定是頁目錄!這種特殊的 PDE 、 PTE 排列方式被多個內存管理函數使用,這些函數由 ntoskrnl.exe 導出。例如,有文檔記載的 API 函數 MmIsAddressValid() 和 MmGetPhysicalAddress() 使用 32 位的線性地址來查找其 PDE ,如可用,還會查找其 PTE ,并會檢查它們的內容。 MmIsAddressValid() 簡單的檢驗目標頁是否位于物理內存中。如果測試失敗,就意味著線性地址或者無效或者該地址引用的頁已經被置換到了后備存儲器(由系統頁面文件集表示)中。 MmGetPhysicalAddress() 首先從線性地址中提取相應的頁幀計數器( PFN ),該 PFN 就是與其相關的物理內存頁(該頁將按照頁大小進行劃分)的基地址。接下來,它通過線性地址中剩余的 12 個位,來計算在物理頁中的偏移量,最后將 PFN 指出的物理頁基地址和前面算出的偏移量相加即可得到該線性地址對應的物理地址。

更徹底的檢查 MmGetPhysicalAddress() 的實現方式,會發現 Windows 2000 內存布局的另一個有趣的特性。 MmGetPhysicalAddress() 函數在開始之前,首先測試線性地址是否位于 0x80000000-----0x9FFFFFFF 。就像前面提到的,這里存放著 hal.dll 和 ntoskrnl.exe ,而且這也是 Windows 2000 使用 4MB 頁的地址塊。這個有趣的特性是,如果給定的線性地址位于這一范圍, MmGetPhysicalAddress() 將不會關心所有的 PDE 或 PTE 。替代的是,該函數簡單的將線性地址的高 3 位設為零,然后加上字節偏移量,最后將得到地址作為物理地址返回。這意味著,物理地址范圍: 0x00000000----0x1FFFFFFF 將按照 1 : 1 的比例映射到線性地址 0x80000000----0x9FFFFFFF !要知道 ntoskrnl.exe 總是被加載到線性地址 0x80400000 ,這意味著 Windows 2000 的內核總位于物理地址 0x00400000 ,這種情況發生在第二個 4MB 頁的基地址位于物理內存中。事實上,通過檢查這些內存區域可以證明上面的假定是正確的。本章提供的 Memory SPY 將使你有機會看到這一點。

補充:

這部分內容選擇自《 Windows 環境下 32 位匯編語言程序設計》

x86 的內存分頁機制

當 x86 CPU 工作在保護模式和虛擬 8086 模式時,可以使用全部 32 根地址線訪問 4GB 的內存。因為 80386 的所有通用寄存器都是 32 位的,所以用任何一個通用寄存器來間接尋址,不必分段就可以訪問到 4GB 的內存地址。

但 這并不意味著,此時段寄存器就不再有用了。實際上,段寄存器更加有用了,雖然在尋址上沒有分段的限制了,但在保護模式下,一個地址空間是否可以被寫入,可 以被多少優先級的代碼寫入,是不是允許執行等等涉及保護的問題就出來了。要解決這些問題,必須對一個地址空間定義一些安全上的屬性。段寄存器這時就派上了 用場。但是設計屬性和保護模式下段的其他參數,要表示的信息太多了,要用 64 位長的數據才能表示。我們把這 64 位的屬性數據叫做段描述符( Segment Descriptor )。

80386 的段寄存器是 16 位的,無法放下保護模式下 64 位的段描述符。如何解決這個問題呢?方法是把所有段的段描述符順序存放在內存中的指定位置,組成一個段描述符表( Descriptor Table );而段寄存器中的 16 位用來做索引信息,指定這個段的屬性用段描述符表中的第幾個描述符來表示。這時,段寄存器中的信息不再是段地址了,而是段選擇器( Segment Selector )。可以通過它在段描述符表中“選擇”一個項目已得到段的全部信息。

那么段描述符表存放在哪里呢? 80386 引入了兩個新的寄存器來管理段描述符表。一個是 48 位的全局描述符表寄存器 GDTR ,一個是 16 位的局部描述符表寄存器 LDTR 。那么,為什么有兩個描述符表寄存器呢?

GDTR 指向的描述符表為全局描述符表 GDT ( Global Descriptor Table )。它包含系統中所有任務都可用的段描述符,通常包含描述操作系統所使用的代碼段、數據段和堆棧段的描述符及各任務的 LDT 段等。全局描述符表只有一個。

LDTR 指向局部描述符表 LDT ( Local Descriptor Table )。 80386 處理器設計成每個任務都有一個獨立的 LDT 。它包含每個任務私有的代碼段、數據段和堆棧段的描述符,也包含該任務所使用的一些門描述符,如任務門和調用門描述符等。

不同任務的局部描述符分別組成不同的內存段,描述這些內存段的描述符當作系統描述符放在全局描述符表中。和 GDTR 直接指向內存地址不同, LDTR 和 CS 、 DS 等段選擇器一樣只存放索引值,指向局部描述符內存段對應的描述符在全局描述符表中的位置。隨著任務的切換,只要改變 LDTR 的值,系統當前的局部描述符表 LDT 也隨之切換,這樣便于個任務之間數據的隔離。但 GDT 并不隨著任務的切換而切換。

16 位的段選擇器如何使用全局描述符表和局部描述符表這兩個表呢?實際上,段選擇器中只有高 13 位表示索引值。剩下的 3 個數據位中,第 0 , 1 位表示程序的當前優先級 RPL ;第 2 位 TI 位用來表示在段描述符的位置; TI=0 表示在 GDT 中, TI=1 表示在 LDT 中。

80386 處理器把 4KB 大小的一塊內存當作一“頁”內存,每頁物理內存可以根據“頁目錄”和“頁表”,隨意映射到不同的線性地址上。這樣,就可以將物理地址不連續的內存的映射連到一起,在線性地址上視為連續。在 80386 處理器中,除了與 CR3 (保存當前頁目錄的地址)相關的指令使用的是物理地址外,其他所有指令都是使用線性地址尋址的。

是否啟用內存分頁機制是由 80386 處理器新增的 CR0 寄存器中的位 31 ( PG 位)決定的。如果 PG=0 ,則分頁機制不啟用,這時所有指令尋址的地址(線性地址)就是系統中實際的物理地址;當 PG=1 的時候, 80386 處理器進入內存分頁管理模式,所有的線性地址要經過頁表的映射才得到最后的物理地址。

標簽: Windows系統
主站蜘蛛池模板: 久草免费看 | 久99re视频9在线观看 | 亚洲一区中文字幕 | 亚洲国产成人久久午夜 | 免费看特级毛片 | 国产成人精品一区二区免费视频 | 草久视频在线观看 | 欧美熟videos肥婆 | 成年人一级片 | 美女视频黄a视频免费全过程 | 九九视频精品在线 | 三级视频中文字幕 | 国产精品美女免费视频大全 | 最刺激黄a大片免费观看下截 | 久久精品亚洲精品一区 | 韩日一级 | 老人久久www免费人成看片 | 午夜视频在线观看一区 | 免费五级在线观看日本片 | 国内精品国语自产拍在线观看55 | 国产只有精品 | 九九精品视频一区二区三区 | 最近韩国日本免费免费版 | 欧美一级毛片免费播放aa | 日本高清视频www夜色资源 | 午夜怡红院 | 92手机看片福利永久国产 | 国产一级高清视频 | 99精品视频在线播放2 | 在线播放亚洲精品 | 亚洲乱视频 | 中国a毛片 | 在线观看视频国产 | 欧美不卡在线视频 | 亚洲美女在线播放 | 国产亚洲精品网站 | 久久久久久国产精品免费免 | 国产网站精品 | 欧美日韩亚洲一区二区三区 | 成人免费观看网欧美片 | 五月久久噜噜噜色影 |