Lab2 是關于作業系統存儲管理的細節。主要是建立記憶體模型,頁表,實體位址映射等。
在Lab2之前,請複習好前序知識:
Lab2記憶體管理準備知識
MIT6.828——Lab1 PartA
MIT6.828——Lab1 PartB
在開始做題之前,需要了解一下一些常用的函數,宏以及記憶體布局,建議複習一下LAB1中的簡單記憶體模型,LAB2預備知識中的相關。這裡有幾個很有用的位址變換工具,具體實作可以檢視<code>mmu.h</code>和<code>pmap.h</code>,提前掌握這些小工具對于了解位址變換和後續的程式編寫有很大幫助。
名稱
參數
作用
PADDR
核心虛拟位址kva
将核心虛拟位址kva轉成對應的實體位址
KADDR
實體位址pa
将實體位址pa轉化為核心虛拟位址
page2pa
頁資訊結構struct PageInfo
通過空閑頁結構得到這一頁起始位置的實體位址
pa2page
通過實體位址pa擷取這一頁對應的頁結構體struct PageInfo
page2kva
通過空閑頁結構得到這一頁起始位置的虛拟位址
PDX
線性位址la
獲得該線性位址la對應的頁目錄項索引
PTX
獲得該線性位址la在二級頁表中對應的頁表項索引
PTE_ADDR(pte)
頁表項或頁目錄項的值
獲得對應的頁表基址或者實體位址基址(低12位為0)

首先關于第一個函數<code>boot_alloc()</code>這是在記憶體管理機制還沒建立起來時,系統記憶體的配置設定函數。在page等建立以後當使用<code>page_alloc()</code>而不該再使用該函數。根據函數的注釋,先記錄目前的free指針,然後将free指針偏移n單元即可,注意記憶體對齊(使用ROUNDUP函數)。
第二個函數是初始化記憶體管理了,隻需要做到check_page_free_list(1)之前即可。
首先使用<code>i386_detect_memory</code>擷取實體記憶體大小;之後建立核心的頁目錄,使用的是<code>boot_alloc()</code>,大小是1頁(4KB);然後将核心頁目錄安裝到一個頁目錄項中;之後建立空閑實體頁數組pages。
第三個函數,建立page相關的資料結構。首先哪些實體記憶體是free的?根據注釋,首先實體記憶體的第0頁需要被标記為已使用;IO-hole需要被标記為已使用,不能被配置設定出去;擴充位址包含核心地方不能被配置設定出去,剩下的空間就可标記為free并後續可以配置設定出去。
第四個函數,是後續應該使用的記憶體配置設定函數<code>page_alloc</code>,根據前面我們知道,<code>page_free_list</code>指着第一個空閑頁,是以隻需要從這個連結清單上摘取一個下來即可。這裡通過前面的幾個函數或者宏,可以将<code>struct PageInfo</code>輕松地對應到實體位址或者虛拟位址。
第五個函數,作用是釋放一個頁。也就是将一個<code>struct PageInfo</code>結構,重新挂回<code>page_free_list</code>。注意不能釋放一個引用值不為0的頁,或者連結值不為空的頁。
這一部分的前序知識,可以看上一篇文章Lab2記憶體管理準備知識。于是開始建立頁表管理。
第一個函數,用于給定一個頁目錄和虛拟位址,傳回對于的頁表項指針。就是一個通路二級頁表找值的過程,上一篇文章中詳細地寫到了。
第二個函數,建立起一段虛拟位址空間和實體位址空間的映射關系,也就是填充頁表的值。
第三個函數,查找一個虛拟位址對應的頁。
第四個函數,取消一個映射關系
第五個函數
繼續完善```mem_init()``
現在可以來一段總結了
這便是JOS目前建立起來的記憶體映射了,左側是實體位址空間,右邊是虛拟位址空間。比如說UVPT,在代碼中有這樣一段
而<code>PDX(UVPT)=1110 1111 01</code>是以位址區間<code>0xef400000~0xef7fffff</code>共計4MB被映射到<code>PADDR(kern_pgdir)</code>處。而正如JOS一開始所說,隻會使用256MB的記憶體,映射關系也滿足。
記憶體映射這塊,需要好好地閱讀代碼,文章中沒有詳細地列出JOS記憶體布局,虛拟記憶體的布局在<code>memlayout.h</code>中
為了更好地了解這部分,需要熟悉保護模式分頁模式下地尋址Lab2記憶體管理準備知識
要區分好實體位址和虛拟位址,頁表,頁目錄這些裡面裝地内容是什麼
要有一個記憶體模型總體上的概念