JOS學習筆記(七)

接前一篇。

上篇日誌主要是完成了一些分頁相關機制的工作,但還沒有真正的去使用這個分頁系統。Lab2的part3部分主要就是讓我們使用part2中完成的映射機制來初始化內核的頁目錄和頁表,並將此頁目錄加載到cr3裏,讓os真正去使用我們初始化之後的頁目錄以取代kernpgdir.c裏面簡單的頁目錄。

在開始之前讓我們看一下JOS的虛擬內存分佈圖,在part3裏的所有工作就是照着此圖實現其中的部分映射。

 首先從高位地址說起,kernbase到最高爲4g是一塊remapped內存,這塊很大的內存從低到高要映射整塊物理內存。

其次kernbase往下PTSIZE(貌似是4M)是無用內存,再往下是KERNSTACKTOP也就是內核棧的棧頂,衆所周知棧的生長順序是從高地址向低地址生長,所以這個位置也就是棧開始生長的位置。從KERNSTACKTOP往下KSTKSIZE爲內核棧區域,大概是8個頁面,內核棧不能超過這個區域。從KERNSTACKTOP往下一個PTSIZE這塊區域除了內核棧之外還有一塊空白區域,防止棧溢出的時候複寫用戶空間的數據。

接着是ULIM,代表用戶空間的最高地址,換句話說此位置往下所有空間爲用戶空間,用戶空間有很多東西,之後的LAB會詳細說明,在此只說UPAGES。

UPAGES是JOS用戶記錄物理頁面使用情況的數據結構,爲了使用戶空間能訪問這塊數據結構,會將PAGES映射到UPAGES位置。

好總結一下,是要總共要求映射3塊區域,,1是映射UPAGES結構,,2是映射內核棧,3映射整塊物理內存。


 

1、UPAGES的映射

所謂映射就是將某個虛擬內存地址(符號地址)映射到實際的物理地址,UPAGES映射到pages也就是通過UPAGES訪問到的地址恰恰是pages這個符號指向的物理地址的內容。而映射的實質就是往頁表和頁目錄裏寫入相應的值,使UPAGES這個符號經過地址變換之後指向的地址恰好是pages的物理地址。

實現的方式很簡單,先獲取pages數組的大小,並向上對齊到PGSIZE得到要映射的頁面,然後一個頁面一個頁面分別映射即可。

容易出錯的地方:(1)不能使用sizeof獲取pages數組的大小,因爲此數組是動態分配的,使用sizeof只會獲取到pages這個指針本身的大小(4B)。(2)一個頁面地址映射一次即可,映射的最小單位是頁面,一個頁面內的地址不需要反覆映射。


2、內核棧的映射。

目前內核棧的符號地址是bootstack表示棧底(棧的低地址,不是邏輯上的棧底反而是邏輯上的棧頂,因爲向下生長),需要將KSTACKTOP-KSTKSIZE映射到這個位置,並向上按順序映射KSTKSIZE大小的內存區域。

其餘部分不用管,雖然函數說明中寫了很多。



3、映射整塊內存區域。

要映射KERNBASE到0xffffffff總共256M內存的空間到從0開始的物理地址。雖然我們沒有足夠的物理空間,但we just set up the mapping anyway。什麼叫just set up the mapping anyway啊,沒有就是沒有,不夠就是不夠,你讓我映射到哪裏去?!抱怨歸抱怨,但我都給映射到了物理的0地址上去了,也算是沒有辦法的辦法。

但這麼映射整塊物理內存會出問題。在page_insert操作中會將該Page結構的pp_ref++,但映射整塊物理內存的過程實際是便利了整個pages數組,這就會導致所有的Page結構的pp_ref++。但別忘了還有個page_free_list串起來了空閒的Page,這些空閒的Page理所應當的pp_ref也被增加了,最後的結果是page_free_list裏面頁面的pp_ref不爲0。在空閒鏈表中的頁面的引用次數不爲0,這很明顯是不符合邏輯的,因此要進行--操作。

當然還有一種解釋是:不這麼做通不過check,至於願意相信哪種隨你好了。

通過這個問題我覺得這算是JOS設計不合理的一個地方,映射和頁面被引用是否是一個概念?誰負責維護pp_ref的信息,是這個頁面的申請者還是page_insert函數還是page_insert的調用者?感覺這些地方還有待商榷。但之前1和2的映射不用考慮這個問題是因爲牽扯到的頁面不在free_page_list裏,這在free_page_list初始化的時候就把裏面的頁面剔除了。


最後,可以看到通過check。



lab2到此結束,lab2和lab1的代碼我上傳到自己的資源裏歡迎下載。

發佈了78 篇原創文章 · 獲贊 14 · 訪問量 48萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章