Windows安全之 內存管理 虛擬地址, 邏輯地址 ,物理內存, 頁表與頁目錄

以32位Windows 為例
物理內存頁, 每0x1000 為一頁 , 頁號(page number)為首地址, 內容為頁面偏移(page offset) ,
由於內存最小單位為頁(4KB)


0x0000
0x1000
0x2000
0x3000
....
0xFFFFF 每次加上一千 最大數為而往後數需要符合頁面內存大小(4KB) 的限制, 最大的頁幀/頁面號為0xFFFFF

最大內存號最大值可以去到0xFFFFF (總數為 : 2^20)

因此帶出以下概念

頁目錄(Page Directory,PD), 管理所有頁目錄項(Page Directory Entry,PDE) , 管理所有物理內存頁的信息 就需要一個大小為2^20的連續內存空間, 沒有可能分配一個1MB的數組,或說是連續空間來處理, 這太不現實也不夠效率,
於是開發OS的大神想到頁目錄(Page Directory)與頁表(Page Table)機制, 目錄內每一項也是4byte, 高20bit存放 頁表(Page Table) 首地址, 低12bit為0
(頁目錄指向1024個不同頁表)

而 頁表(Page Table), 頁表中每一個內容 為4byte , 一共有1024項 , 即大小為4KB , 高20bit為物理頁的物理地址, 低12bit為物理表面的設置 (如讀,寫,保護等)
(頁表指向1024個不同物理內存頁)

意思就是 頁目錄有1024個指針,指向1024個頁表(Page Table), 然後每1個頁表,指向1024個地址全是物理頁的物理地址, 透過物理頁的首地址加上虛擬地址低12位的偏移, 最後容易地算出物理地址


那頁目錄*頁表就是1024*1024 剛好是 2^20 = 1MB 是32位操作系統的內存頁總數

對於x86系統, 頁目錄的物理地址存放在CR3寄存器

-----------------------------------------------

轉換地址過程:
地址結構



1. 首先找到頁目錄所在的物理頁
2. 按照虛擬地址中的 32-22bit(位) 找到 PDE 地址
3. 通過頁目錄項的首 20bit(位) 找到了頁表地址
4. 通過頁表中使用 虛擬地址最低12位(21-12), 找到頁表索引, 最後得到的物理頁地址
5. 最後一步, 通過虛擬地址的0-12位, 即地址中的0xFFFFF000, 最後3個位作為偏移(offset) , 最後把物理頁地址跟偏移相加 = 物理地址

如FFFFF024 , 那他偏移就為024, 123456789 那偏移就是789

整個流程就是, 虛擬地址->頁目錄得出頁表->頁表得出物理頁面地址->物理面頁加上偏移得出物理地址-> 物理地址

而 2^10 能夠索引到1024個位置, 而2^12 能夠索引到4096 剛好為一個頁面大小的所有位置,

這樣一來, 經過這套機制, 就能有效地分配內存 , 在分配虛擬地址後, 能快速地找到對應的物理位置

補充: 當系統有虛擬地址時, 但我們沒有使用讀寫操作, 那他是沒有對應的物理地址的

關係圖 虛擬內存->頁目錄->頁表->物理內存




--------

在windows內核中 有三個內存分配隊列

A : 已分配的內存隊列
B : 待清理的內存隊列 (清零)
C : 空閒隊列 (存放可使用的內存)

流程如下:

1. 每隔一段時間, 系統會從隊列B中抽取給隊列C
2. 每當程序釋放內存時, 系統在隊列A抽取放到隊列B
3. 申請內存時, 系統在隊列C中, 放到隊列A

因此不會造成分配沖突


Comments

Popular posts from this blog

Android Kernel Development - Kernel compilation and Hello World

How does Nested-Virtualization works?

Understanding ACPI and Device Tree