要记得好好看文档,文档里的图解很详细。不过这次完全看注释都可以写出来。
目录
流程
lab3 主要是实现虚拟内存管理,涉及到了 swap 文件系统,不过这个的具体实现又不需要我们操心,驱动和接口都帮我们实现了,我们只依据 struct swap_manager
的接口,实现一下换页算法就好。
不太想具体了解驱动,硬盘驱动大概扔在 kern/drivers/ide.c ,爱看看吧。
这次试验真的很良心。
练习0:填写已有实验
vim 大法好。
练习1:给未被映射的地址映射上物理页(需要编程)
在 kern/mm/vmm.c 中,有很长的一大段注释,讲得很明白,对着写就好了。
注释全都告诉你了,先通过 get_pte
拿到 PTE ,其中第一个参数在 mm->pgdir
中,第三个参数你应当设置为 1 ,第二个参数猜都能猜出来。然后接着注释里说的,如果该页未被设置,你需要调用 pgdir_alloc_page
来映射物理地址和线性地址,然后自己做一下错误处理即可。
接下来的注释是第二个任务的内容,不过可以顺便写好。
马上就可以完成……
ptep = get_pte(mm->pgdir, addr, 1);
if (ptep == NULL) goto failed;
if (*ptep == 0) {
if (pgdir_alloc_page(mm->pgdir, addr, perm) == NULL) goto failed;
} else if (swap_init_ok) {
struct Page *page;
ret = swap_in(mm, addr, &page);
if (ret != 0) goto failed;
ret = page_insert(mm->pgdir, page, addr, perm);
if (ret != 0) goto failed;
ret = swap_map_swappable(mm, addr, page, 1);
if (ret != 0) goto failed;
page->pra_vaddr = addr;
} else goto failed;
需要注意的是注释里没有提到的 struct Page
多了一个成员 pra_vaddr
,它是在换出的时候指明换出内存的哪个页的。之前没注意到这里需要设置,一直跑不过测试,看了参考答案才注意到(调试是不可能调试的,这辈子都不可能调试的)。
那俩问题好像和 lab2 一样的,这就不重复了。
练习2:补充完成基于FIFO的页面替换算法(需要编程)
一部分在 kern/mm/vmm.c ,另一部分在 kern/mm/swap_fifo.c 中。 fifo swap 也是通过链表维护 FIFO 队列的,两个函数里只要对链表进行简单操作就好了。
map_swappable
成员函数是在被移出链表之后加入回链表的操作,根据算法要求只需要简单加回到链表头部即可。
swap_out_victim
是选择不需要的页换入硬盘的操作,根据算法要求只需要在队尾取出一项,按注释所说的从链表中删去,并将 *ptr_page
设置为该页即可。
static int
_fifo_map_swappable(struct mm_struct *mm, uintptr_t addr, struct Page *page, int swap_in) {
list_entry_t *head=(list_entry_t*) mm->sm_priv;
list_entry_t *entry=&(page->pra_page_link);
assert(entry != NULL && head != NULL);
list_add(head, entry);
return 0;
}
static int
_fifo_swap_out_victim(struct mm_struct *mm, struct Page ** ptr_page, int in_tick) {
list_entry_t *head=(list_entry_t*) mm->sm_priv;
assert(head != NULL);
assert(in_tick==0);
list_entry_t *tail = head->prev;
list_del(tail);
struct Page *page = le2page(tail, pra_page_link);
*ptr_page = page;
return 0;
}
后记
挑战?咕,下次再说。