1. 修改sysproc.c 中的sys_sbrk()函数
1
2
3
4
5
6
7
8
9
10
11
12
13
14
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;
}
  1. 修改vm.c中的mappages:删除static关键字
  2. 修改trap.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
// 在开头声明
int mappages(pde_t *pgdir, void *va, uint size, uint pa, int perm);

// 在trap()中添加page fault处理
/*前面的源代码
case T_IRQ0 + IRQ_SPURIOUS:
cprintf("cpu%d: spurious interrupt at %x:%x\n",
cpuid(), tf->cs, tf->eip);
lapiceoi();
break;
*/
// 新增
case T_PGFLT: // trap 14 - page fault
{
struct proc *p = myproc();

// 只处理用户空间的 page fault
if(p == 0 || (tf->cs & 3) == 0){
cprintf("kernel page fault at eip 0x%x, va 0x%x\n", tf->eip, rcr2());
panic("trap");
}

uint va = rcr2();
uint addr = PGROUNDDOWN(va); // 对齐到页边界

// 检查地址是否在进程的有效范围内,地址应该小于 sz 但大于栈顶
if(addr >= p->sz || addr < PGROUNDDOWN(p->tf->esp)) {
// 无效地址:超出堆顶或在栈下方
cprintf("pid %d %s: invalid page fault at va 0x%x (sz=0x%x, esp=0x%x)\n",
p->pid, p->name, va, p->sz, p->tf->esp);
p->killed = 1;
break;
}

// 分配一页物理内存
char *mem = kalloc();
if(mem == 0){
cprintf("lazy allocation: out of memory for va 0x%x\n", va);
p->killed = 1;
break;
}

// 清零新分配的页
memset(mem, 0, PGSIZE);

// 映射到用户虚拟地址空间
if(mappages(p->pgdir, (void*)addr, PGSIZE, V2P(mem), PTE_W|PTE_U) < 0){
cprintf("lazy allocation: mappages failed for va 0x%x\n", va);
kfree(mem);
p->killed = 1;
break;
}

return;
}
  1. 关闭系统调用跟踪:syscall.c
1
2
// 注释掉:
// cprintf("%s -> %d\n", syscall_names[num], curproc->tf->eax);
  1. 编译测试
1
2
3
4
5
6
make clean
make
make CPUS=1 qemu-nox
ls
echo hi
cat README