資源
練習1:給未被映射的地址映射上物理頁
題目
完成do_pgfault(mm/vmm.c)函數,給未被映射的地址映射上物理頁。設置訪問權限的時候須要參考頁面所在 VMA 的權限,同時須要注意映射物理頁時須要操做內存控制結構所指定的頁表,而不是內核的頁表。注意:在LAB3 EXERCISE 1處填寫代碼。執行make qemu後,若是經過check_pgfault函數的測試後,會有「check_pgfault() succeeded!」的輸出,表示練習1基本正確。git
請在實驗報告中簡要說明你的設計實現過程。請回答以下問題:github
- 請描述頁目錄項(Page Directory Entry) 和頁表項(Page Table Entry) 中組成部分對ucore實現頁替換算法的潛在用處。
- 若是ucore的缺頁服務例程在執行過程當中訪問內存,出現了頁訪問異常,請問硬件要作哪些事情?
解答
個人設計實現過程
do_pgfault函數已經完成了參數檢查及錯誤檢查等流程,根據註釋不難完成剩下的流程。算法
-
檢查頁面異常發生時的錯誤碼的最低兩位,即存在位和讀/寫位,若是發現錯誤則打印相關提示信息並返回。致使錯誤的緣由有:讀沒有讀權限的內存、寫沒有寫權限的內存、所讀內容在內存中卻讀失敗等。(原代碼中已實現)編程
-
用虛擬地址addr索引頁目錄表和頁表,獲得對應的頁表項。這時要分兩種狀況討論。app
-
若是頁表項爲0,說明系統還沒有爲虛擬地址addr分配物理頁,所以首先須要申請分配一個物理頁;而後設置頁目錄表和頁表,以創建虛擬地址addr到物理頁的映射;最後,設置該物理頁爲swappable,而且把它插入到可置換物理頁鏈表的末尾。框架
-
若是頁表項不爲0,而又出現缺頁異常,說明系統已創建虛擬地址addr到物理頁的映射,但對應物理頁已經被換出到磁盤中。這時一樣須要申請分配一個物理頁,把換出到磁盤中的那個頁面的內容寫到該物理頁中;接下來和步驟3相似,一樣須要創建虛擬地址addr到物理頁的映射,一樣須要把該物理頁插入到可置換頁鏈表的末尾。函數
問題1:頁目錄項和頁表項對頁替換算法的用處
答:頁替換涉及到換入換出,換入時須要將某個虛擬地址vaddr對應於磁盤的一頁內容讀入到內存中,換出時須要將某個虛擬頁的內容寫到磁盤中的某個位置。而頁表項能夠記錄該虛擬頁在磁盤中的位置,爲換入換出提供磁盤位置信息。頁目錄項則是用來索引對應的頁表。測試
問題2:缺頁服務例程出現頁訪問異常時,硬件須要作哪些事情
答:優化
- 關中斷
- 保護現場。包括:將頁訪問異常的錯誤碼壓入內核棧的棧頂、將致使頁訪問異常的虛擬地址記錄在cr2寄存器中、保存狀態寄存器PSW及斷點等。
- 根據中斷源,跳轉到缺頁服務例程
代碼優化
對照答案對代碼進行優化。this
- 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置換算法,選擇可換出物理頁鏈表的首元素,做爲將被換出的物理頁。