进程内存布局

理解这一张图是理解 xv6 的关键。

用户虚拟地址空间 (User Virtual Address Space)

从 0 开始向上生长:

  • Text (Code): 代码段。
  • Data: 全局变量。
  • Stack: 用户栈。动态生长。
  • Heap: 堆。通过 sbrk() 系统调用向上生长。
  • Trampoline & Trapframe: 在极高地址处(虚拟地址顶部),映射了用于处理中断跳板代码。这部分对用户是不可读写的(PTE_U 位未置位),但必须在页表里。

两个栈 (The Two Stacks)

这是初学者最容易晕的地方:一个进程有两个栈。

  1. 用户栈 (User Stack): 当你在用户态执行 call function 时用。
  2. 内核栈 (Kernel Stack): 当你执行 syscall 陷入内核后,CPU 的 sp 寄存器会切换指向这里。内核代码(如 sys_open)的局部变量存在这里。

隔离性: 用户程序无法直接访问内核栈。如果用户栈爆了,只是程序崩;如果内核栈爆了,OS 崩。