这里做一个lab2的总结
页面管理总览
本lab中设计并实现了一个二级页表,其中页目录和页表索引的信息都交由内核管理,并且将物理页面数列对应结构体映射到虚拟地址UPAGES上。并将低地址的256MB的物理内存映射到虚拟地址上的0xf0000000开始的256MB虚拟内存上,所以说我们的可寻址地址空间是4GB,但是这是由32位机器决定出来的。真正可以使用的空闲空间,大致只有三块。用户可以使用的只有一块。
所有的工作都在mem_init中完成,总览下来,可以分为内存分配,页面结构初始化,映射物理页面。
页面布局
页目录的物理地址储存到了第一个可以分配的页面里,也就是mem_init
开始便调用了boot_alloc
,紧接着的就是管理物理页面的结构体数组pages
,到这里,其实二级页表就已经基本构建完成了。我们按照流程来理一遍:首先cpu给出一个va(虚拟地址),然后交由mmu进行处理并寻址找到对应的物理页面——重点来看一下这个寻址过程。va所对应的高10位也就是对应的页目录的偏移地址,通过这个值加上寄存器中储存的页表基址,得到一个PTE,对应着二级页表的页表号。之后拿着这个页表号去加上va中对应的二级页表偏移得到最后一个PTE,通过这个PTE以及va的低12位,就可以找到一张确定的物理页面,并找到该页面中的特定偏移。
对于本lab中,页目录的基址也就是pgdir,而页表号是多少呢??
static inline physaddr_t
page2pa(struct PageInfo *pp)
{
return (pp - pages) << PGSHIFT;
}
从上面这个函数(页面转换为物理地址),可以知道,我们将某一张物理页面相对于pages数组的偏移并左移位12位作为某个二级页表的起始物理地址。我个人感觉,这是一个很巧妙的设计,这样子每个物理界面的起始地址页自然而然从0开始。同时由于之前在page_init
中存入了可以使用和不可以使用的物理页面,这样,pages就是刚好与地址相对应。最后直接拿到二级页表的PTE,访问最后的物理地址,通过I/O总线访问RAM,得到最终的内容