HW4 xv6 lazy page allocation

Homework: xv6 lazy page allocation

本次作业要求实现一个对堆内存的延迟分配。

实验链接:https://pdos.csail.mit.edu/6.828/2018/homework/xv6-zero-fill.html

Part One:Eliminate allocation from sbrk()

第一个任务是删除掉sbrk(n)系统调用实现,在sysproc.c中,手动注释掉该函数。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
int
sys_sbrk(void)
{
int addr;
int n;

if(argint(0, &n) < 0)
return -1;
addr = myproc()->sz;
/*if(growproc(n) < 0)
return -1;
*/
myproc()->sz += n;
return addr;
}

growproc(n)给注释掉过后,会出现以下的问题,该中断可以在trap.c中找到,终中断号14,发生page fault,在虚拟地址的0x4004引起该错误。

page fault

为什么会发生该错误呢?当我们注销掉growproc(n)过后?首先,growproc(n)函数,如果n是正数,会分配1个或者多个的物理内存页,并且将他们映射到调用该系统调用的进程空间的顶部;如果n是负数,则会从进程地址空间取消一个或者多个页并且释放相对应的物理页。也就是说,虽然我们改了进程的地址空间大小,但是没有具体映射到物理内存,就会导致该虚拟内存页错误。

Part Two:Lazy allocation

在trap.c中实现一个延迟分配,只需要当虚拟内存发生页错误的时候,再触发分配物理内存。

首先,我们可以从cprintf中发现,发生错误的地址是保存在cr2寄存器中,我们需要将该地址读出来,然后拿到它地址开始到一整个内存页的大小,然后未这个虚拟内存也创建物理内存页,并且进行映射。按照这样的思路喝题目提示,我们可以进行响应的代码编写。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// page fault implemation

if(tf->trapno == T_PGFLT){
uint va = PGROUNDDOWN(rcr2());
if(va < myproc()->sz){
char *mem = kalloc();
if(mem == 0){
cprintf("out of memory!\n");
exit();
return;
}
memset(mem, 0, PGSIZE);
cprintf("kernel faulting in page at %x\n", va);
mappages(myproc()->pgdir, (char *)va, PGSIZE, V2P(mem), PTE_W | PTE_U);
return;
}
}

此处的mappages函数,在vm.c中是一个静态的函数,因此需要将其static修改掉,并且在trap.c中添加其函数定义进行链接 int mappages(pde_t *pgdir, void *va, uint size, uint pa, int perm);

lazy allocation结果


HW4 xv6 lazy page allocation
https://www.bencorn.com/2022/07/11/HW4-xv6-lazy-page-allocation/
作者
Bencorn
发布于
2022年7月11日
许可协议