Skip to content

proc.h

TIP

专用于内核上下文切换时保存的寄存器。 RISC-V的调用约定中,callee-saved寄存器(s0-s11)由被调用函数负责保存和恢复。 ra 是返回地址(return address),sp 是栈指针(stack pointer)。 当一个函数(调用者)调用另一个函数(被调用者)时,被调用者不能随意修改这些寄存器, 如果需要使用,必须在函数开始时将它们的值保存在栈上,在函数返回前再从栈上恢复。 这样做可以确保调用者函数在子函数返回后,其寄存器状态保持不变。

struct context {
  uint64 ra;
  uint64 sp;

TIP

Callee-saved registers (被调用者保存的寄存器)

  uint64 s0;
  uint64 s1;
  uint64 s2;
  uint64 s3;
  uint64 s4;
  uint64 s5;
  uint64 s6;
  uint64 s7;
  uint64 s8;
  uint64 s9;
  uint64 s10;
  uint64 s11;
};

TIP

每个CPU核心维护一个cpu结构体,记录其自身的状态信息。

struct cpu {
  struct proc *proc;
  struct context context;
  int noff;
  int intena;
};

extern struct cpu cpus[NCPU];

TIP

trapframe结构体用于在用户态和内核态之间切换时,保存和恢复进程的上下文。 当发生系统调用、异常或中断时,硬件或软件会将用户进程的寄存器等状态保存在这个结构体中, 以便在内核处理完毕后,能够精确地恢复到用户态的执行点。 uservec (定义于 trampoline.S) 会将用户寄存器保存到trapframe, 然后从trapframe中加载kernel_sp, kernel_hartid, kernel_satp等内核关键信息, 并跳转到kernel_trap开始内核处理流程。 usertrapretuserret (定义于 trampoline.S) 则执行相反的操作, 它们设置trapframe中的kernel_*字段,恢复用户寄存器,切换回用户页表,然后返回用户空间。 trapframe也保存了callee-saved寄存器 (s0-s11),因为从内核态返回用户态的过程 不会经过完整的函数调用栈返回,需要手动恢复这些寄存器。

struct trapframe {
  /*   0 */ uint64 kernel_satp;
  /*   8 */ uint64 kernel_sp;
  /*  16 */ uint64 kernel_trap;
  /*  24 */ uint64 epc;
  /*  32 */ uint64 kernel_hartid;
  /*  40 */ uint64 ra;
  /*  48 */ uint64 sp;
  /*  56 */ uint64 gp;
  /*  64 */ uint64 tp;
  /*  72 */ uint64 t0;
  /*  80 */ uint64 t1;
  /*  88 */ uint64 t2;
  /*  96 */ uint64 s0;
  /* 104 */ uint64 s1;
  /* 112 */ uint64 a0;
  /* 120 */ uint64 a1;
  /* 128 */ uint64 a2;
  /* 136 */ uint64 a3;
  /* 144 */ uint64 a4;
  /* 152 */ uint64 a5;
  /* 160 */ uint64 a6;
  /* 168 */ uint64 a7;
  /* 176 */ uint64 s2;
  /* 184 */ uint64 s3;
  /* 192 */ uint64 s4;
  /* 200 */ uint64 s5;
  /* 208 */ uint64 s6;
  /* 216 */ uint64 s7;
  /* 224 */ uint64 s8;
  /* 232 */ uint64 s9;
  /* 240 */ uint64 s10;
  /* 248 */ uint64 s11;
  /* 256 */ uint64 t3;
  /* 264 */ uint64 t4;
  /* 272 */ uint64 t5;
  /* 280 */ uint64 t6;
};

TIP

定义进程可能处于的几种状态

enum procstate {
  UNUSED,
  USED,
  SLEEPING,
  RUNNABLE,
  RUNNING,
  ZOMBIE
};

TIP

proc结构体是进程控制块(PCB),包含了单个进程的所有状态信息。

struct proc {
  struct spinlock lock;

TIP

p->lock 保护以下字段:

  enum procstate state;
  void *chan;
  int killed;
  int xstate;
  int pid;

TIP

wait_lock 保护以下字段(用于父子进程间的等待关系):

  struct proc *parent;

TIP

以下字段为进程私有,通常只在进程自己的上下文中修改,因此大多时候不需要锁保护

  uint64 kstack;
  uint64 sz;
  pagetable_t pagetable;
  struct trapframe *trapframe;
  struct context context;
  struct file *ofile[NOFILE];
  struct inode *cwd;
  char name[16];
};