資源
練習1:給未被映射的地址映射上物理頁
題目
完成do_pgfault(mm/vmm.c)函數,給未被映射的地址映射上物理頁。設置訪問權限的時候需要參考頁面所在 VMA 的權限,同時需要注意映射物理頁時需要操作內存控制結構所指定的頁表,而不是內核的頁表。注意:在LAB3 EXERCISE 1處填寫代碼。執行make qemu后,如果通過check_pgfault函數的測試后,會有“check_pgfault() succeeded!”的輸出,表示練習1基本正確。
請在實驗報告中簡要說明你的設計實現過程。請回答如下問題:
- 請描述頁目錄項(Page Directory Entry) 和頁表項(Page Table Entry) 中組成部分對ucore實現頁替換算法的潛在用處。
- 如果ucore的缺頁服務例程在執行過程中訪問內存,出現了頁訪問異常,請問硬件要做哪些事情?
解答
我的設計實現過程
do_pgfault函數已經完成了參數檢查及錯誤檢查等流程,根據注釋不難完成剩下的流程。
-
檢查頁面異常發生時的錯誤碼的最低兩位,即存在位和讀/寫位,如果發現錯誤則打印相關提示信息並返回。導致錯誤的原因有:讀沒有讀權限的內存、寫沒有寫權限的內存、所讀內容在內存中卻讀失敗等。(原代碼中已實現)
-
用虛擬地址addr索引頁目錄表和頁表,得到對應的頁表項。這時要分兩種情況討論。
-
如果頁表項為0,說明系統尚未為虛擬地址addr分配物理頁,因此首先需要申請分配一個物理頁;然后設置頁目錄表和頁表,以建立虛擬地址addr到物理頁的映射;最后,設置該物理頁為swappable,並且把它插入到可置換物理頁鏈表的末尾。
-
如果頁表項不為0,而又出現缺頁異常,說明系統已建立虛擬地址addr到物理頁的映射,但對應物理頁已經被換出到磁盤中。這時同樣需要申請分配一個物理頁,把換出到磁盤中的那個頁面的內容寫到該物理頁中;接下來和步驟3類似,同樣需要建立虛擬地址addr到物理頁的映射,同樣需要把該物理頁插入到可置換頁鏈表的末尾。
問題1:頁目錄項和頁表項對頁替換算法的用處
答:頁替換涉及到換入換出,換入時需要將某個虛擬地址vaddr對應於磁盤的一頁內容讀入到內存中,換出時需要將某個虛擬頁的內容寫到磁盤中的某個位置。而頁表項可以記錄該虛擬頁在磁盤中的位置,為換入換出提供磁盤位置信息。頁目錄項則是用來索引對應的頁表。
問題2:缺頁服務例程出現頁訪問異常時,硬件需要做哪些事情
答:
- 關中斷
- 保護現場。包括:將頁訪問異常的錯誤碼壓入內核棧的棧頂、將導致頁訪問異常的虛擬地址記錄在cr2寄存器中、保存狀態寄存器PSW及斷點等。
- 根據中斷源,跳轉到缺頁服務例程
代碼優化
對照答案對代碼進行優化。
- do_pgfault調用get_pte時沒有檢查返回值。
我的代碼:
pte_t *ptep = get_pte(mm->pgdir, addr, 1);
答案的代碼:
pte_t *ptep=NULL;
// try to find a pte, if pte's PT(Page Table) isn't existed, then create a PT.
// (notice the 3th parameter '1')
if ((ptep = get_pte(mm->pgdir, addr, 1)) == NULL) {
cprintf("get_pte in do_pgfault failed\n");
goto failed;
}
- do_pgfault調用pgdir_alloc_page和swap_in失敗后沒打印錯誤信息以方便定位。
我的代碼:
if (*ptep == 0) {
if (page = pgdir_alloc_page(mm->pgdir, addr, perm)) {
ret = 0;
}
}
else if (swap_init_ok) {
swap_in(mm, addr, &page);
if (0 == page_insert(mm->pgdir, page, addr, perm)) {
swap_map_swappable(mm, addr, page, 0);
ret = 0;
}
}
答案的代碼:
if (*ptep == 0) { // if the phy addr isn't exist, then alloc a page & map the phy addr with logical addr
if (pgdir_alloc_page(mm->pgdir, addr, perm) == NULL) {
cprintf("pgdir_alloc_page in do_pgfault failed\n");
goto failed;
}
}
else { // if this pte is a swap entry, then load data from disk to a page with phy addr
// and call page_insert to map the phy addr with logical addr
if(swap_init_ok) {
struct Page *page=NULL;
if ((ret = swap_in(mm, addr, &page)) != 0) {
cprintf("swap_in in do_pgfault failed\n");
goto failed;
}
page_insert(mm->pgdir, page, addr, perm);
swap_map_swappable(mm, addr, page, 1);
page->pra_vaddr = addr;
}
else {
cprintf("no swap_init_ok but ptep is %x, failed\n",*ptep);
goto failed;
}
}
練習2:補充完成基於FIFO的頁面替換算法(需要編程)
題目
完成vmm.c中的do_pgfault函數,並且在實現FIFO算法的swap_fifo.c中完成map_swappable和swap_out_victim函數。通過對swap的測試。注意:在LAB3 EXERCISE 2處填寫代碼。執行make qemu后,如果通過check_swap函數的測試后,會有“check_swap() succeeded!”的輸出,表示練習2基本正確。
請在實驗報告中簡要說明你的設計實現過程。
請在實驗報告中回答如下問題:
- 如果要在ucore上實現"extended clock頁替換算法",請給出你的設計方案,現有的swap_manager框架是否足以支持在ucore中實現此算法?如果是,請給出你的設計方案。如果不是,請給出你的新的擴展和基此擴展的設計方案。並需要回答如下問題:
- 需要被換出的頁的特征是什么?
- 在ucore中如何判斷具有這樣特征的頁?
- 何時進行換入和換出操作?
解答
我的設計實現過程
練習1中結合do_pgfault函數大致分析了缺頁異常處理的流程,但對換入換出只作了簡略討論。這里結合swap_fifo.c的map_swappable和swap_out_victim函數進一步討論換入換出流程。
-
為支持換入換出,在lab 2的基礎上主要修改了兩個地方:一是當虛擬頁被換出到磁盤時,用對應頁表項的高24位記錄磁盤地址;二是在Page結構體中增加了pra_page_link和pra_vaddr兩個字段,前者用於將可換出的物理頁保存在一個鏈表中,后者用於記錄當前物理頁對應的虛擬頁地址(由於可以換入換出,同一個物理頁在不同時刻可能被映射到不同的虛擬頁,因此有必要增加一個字段記錄當前映射到的虛擬頁地址)。
-
map_swappable函數根據FIFO置換算法,將一個物理頁添加到可換出物理頁鏈表的末尾,同時更新物理頁對應的虛擬頁地址。
-
swap_out_victim函數根據FIFO置換算法,選擇可換出物理頁鏈表的首元素,作為將被換出的物理頁。