內核知識第八講,PDE,PTE,頁目錄表,頁表的內存管理


      內核知識第八講,PDE,PTE,頁目錄表,頁表的內存管理

一丶查看GDT表.

我們通過WinDbg + 虛擬機可以進行雙機調試.調試一下看下GDT表

我們知道,GDT表中.存儲的是存儲段信息. 保存了一系列的段和內存的屬性.

但是微軟並沒有使用.

我們可以通過ring3的段寄存器. 當作GDT表的下標.進行查表. 查詢GDT表.

例如我們用OD隨便打開一個ring3的exe,然后看下段和虛擬地址.:

虛擬地址: 0040256f  段選擇子: cs:1B

那么此時段選擇字當下表.虛擬地址當作偏移.去查詢GDT表

下圖為選擇子結構

段選擇子結構:

 首先先拆分選擇子.

1B =   0000000000011 011

查詢出來下表為3,那么去GDT表的第三項進行查找.

然后我們從中取出段首地址 加上我們的偏移

00000000  + 40256F = 0040256F(線性地址)

那么通過查詢GDT表.那么可以找到線性地址. 而我們GDT表,微軟沒有使用它來進行進程隔離. 

PS: 微軟因為不使用GDT表進行進程隔離,所以段選擇子都是一樣的.基地址都是0,我們的虛擬地址就是線性地址.

如果沒有開分頁保護.那么就是物理地址了.但是注意FS寄存器. FS寄存器很特殊.並不能說GDT表沒用.

二丶控制寄存器CR0

我們上面說過.如果沒有開啟分頁保護.那么虛擬地址就是線性地址,線性地址就是物理地址

而微軟是通過分頁進行進程內存的隔離的.

首先說一下什么分頁的歷史,和CR0控制寄存器.

在保護模式下, 寄存器CR0的高位1表示開啟分頁.0表示不開啟.

而這個在操作系統初始化的是否就已經完成了.

如果我們不開啟,那么訪問虛擬內存,就等價於訪問物理內存了.

但是我們的三環是不可以操作的.這個屬於特權指令.如果用匯編進行操作.例如:

__asm mov cr0,8000000

程序會崩潰,提示你權限不夠,並且報告錯誤碼為 C096

但是我們0環可以進行操作的.

看一下CR0的結構:

但是我們0環可以進行操作的.

 

此圖是從inter手冊上截圖下來的.有興趣的可以查詢CR0查看.

剛才我們說的高位為1的是否就去掉分頁保護,此時訪問虛擬內存 等價於訪問物理內存,其實我們修改的是PG位

關於位怎么說的,inter手冊也說.這里我總結一下重要的,如果不相信我可以查看inter手冊.

PG:  PG位表示是否分頁管理機制是否有效. PG = 1,有效, PG = 0 無效.

WP: Wp位 寫保護位, WP為0禁用寫保護,為1則啟動  

PS: 通過修改WP位可以進行過保護. 詳情請看 https://www.cnblogs.com/hongfei/archive/2013/06/18/3142162.html 轉載

三丶分頁管理機制

講解分頁管理機制之前,我們要明白以下幾個關鍵詞的意思.

頁碼:

  在80386下,一個頁的固定大小是4K個字節,也就是4096,一個頁的辯解地址,不許死4K的倍數.

所以4G大小的內存.就可以划分為1M個節. 而我們的頁的開始一般具有一個特點.

比如我們的虛擬地址:

  004010123,而頁的首地址是00401000

后12位都是0.

所以我們把頁的高20位稱為頁碼.

 

進程內存的保護.

進程內存的保護就通過頁的方式進行保護的.

 

 當我們的線性地址轉化為物理地址的是否,會進行查表. 進而查詢到物理地址是那個.

微軟采用的是這種方式.

 

 線性地址轉物理地址需要注意的頁問題.

這個問題則是頁的映射.

我們知道,頁碼是高20位,那么低12為就是偏移了.

當32位的線性地址轉為32為的物理地址的是否,只需要記錄頁碼就可以了.低12位都是一樣的.所以不用記錄.

比如線性地址:

  004010123 映射到物理地址 002010123

那么我只需要記錄前20位即可.

  004010  -> 002010   ,然后物理地址加上我們的后12位即可. 002010+123 = 002010123

四丶線性地址到物理地址的轉換.

 

我們說過,操作系統為了隔離內存.采用了分頁管理.而我們線性地址轉化到物理地址的時候.

則需要查表.

那么我們覺着這個表應該怎么做?

 

物理地址

Xxxx

內存保護屬性

 類似於這樣,我們只需要讓虛擬地址當標進行查表即可.

我們每一個進程都提供這樣的一張表.但是在那個時代.資源是匱乏的.我們這樣做.開不了幾個進程內存就會耗光了.

所以微軟提供了自己的表.而硬件上也提供了支持.

我們看下微軟的表.

首先我們的CR3寄存器保存了表的首地址.

這里有一個頁目錄表,還有頁表的關鍵詞.

頁目錄表: 也稱為PDE,而頁表稱之為PTE.

CPU會通過虛擬地址,當作下表.去頁目錄表中查詢.然后查到的結果再去頁表中查詢.這樣就查到對應的物理地址了.

PDE表的大小:

  頁目錄表,存儲在一個4K字節的物理頁中,其中每一項是4個字節.保存了頁表的地址.

  而最大是1M個頁.

PTE表的大小.

  PTE的大小也和PDE一樣的.

微軟為什么這樣設計.有人會問.這樣設計不就資源用的更多了嗎.其實不是的. 雖然我們設計怎么大.

但是通過兩個表查詢.可以映射4G內存.而上面的設計方法不行.

 

 

首先前邊20位保存了頁表或者物理地址的基地址.

比如我們的頁目錄表. 查到了第5項.那么從中取出千20位來,加上000就等於頁表了. 

然后從頁表中查詢千20位.+虛擬地址的偏移就等價於實際的物理地址了.

 

AVL 位: 可利用位.

D    位: 表示這個分頁是否寫過.

A   位: 表示這個分頁是否讀過

U/S位: 表示這個分頁是否用戶可以訪問還是ring0可以訪問.

R/W位: 內存保護位. 可讀可寫可執行. 還是可讀可執行.

P   位:   內存是否有效.

 

R/W位: 注意我這里說的有兩種方式. 可讀可執行,和可讀可寫可執行.  有沒有發現,我們的Ring3程序.不過是那個內存區域也好.都是可以讀的.

而我們Ring3下的修改內存分頁保護屬性,其實就是將這個頁表的這個RW位進行置位.

 

而我們的虛擬地址當作下表進行查表. 我們的虛擬地址不是分為了20位了嗎. 前10位當作 頁目錄表的下表. 后10位當作頁表的下表

 

設有物理地址為:

  00401 000

那么下表則為:

  00401 = 0000000001 0000000001

通過虛擬地址得知,頁目錄表是第一項,而頁表也是第一項.

 

設頁目錄表第一項為

    003f0111,  此時頁表為 取前20位,加上3個0.  003f0 + 000 = 003f0000

設頁表為
        00201456, 此時取出前20位加上虛擬地址的后邊20位偏移 物理地址= 00201 + 000 = 00201000,那么物理地址就是201000

圖示:

  

設虛擬地址為00402567H, 取出前20位. 分為高10位,和低10位做 PDE,和PTE的索引.

然后進行查表.

最后的通過PTE查詢的高20位加上原虛擬地址的低12位, 然后就找到了物理地址.

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM