Skip to content

进程锁定

与每个进程关联的锁(p->lock)是xv6中最复杂的锁。一种简单的思考p->lock的方式是,在读取或写入以下任何struct proc字段时必须持有它:p->statep->chanp->killedp->xstatep->pid。这些字段可以被其他进程或其他CPU上的调度器线程使用,所以它们必须由一个锁来保护是很自然的。

然而,p->lock的大多数用途是保护xv6进程数据结构和算法的更高级别的方面。以下是p->lock所做的全部事情:

  • p->state一起,它防止了为新进程分配proc[]槽位时的竞争。
  • 它在进程创建或销毁时将其隐藏起来。
  • 它防止父进程的wait收集一个已经将其状态设置为ZOMBIE但尚未让出CPU的进程。
  • 它防止另一个CPU的调度器在让出进程将其状态设置为RUNNABLE之后但在完成swtch之前决定运行它。
  • 它确保只有一个CPU的调度器决定运行一个RUNNABLE的进程。
  • 它防止定时器中断导致进程在swtch中让出。
  • 与条件锁一起,它有助于防止wakeup忽略一个正在调用sleep但尚未完成让出CPU的进程。
  • 它防止kill的受害者进程在kill检查p->pid和设置p->killed之间退出并可能被重新分配。
  • 它使killp->state的检查和写入成为原子操作。

p->parent字段由全局锁wait_lock而不是p->lock保护。只有一个进程的父进程会修改p->parent,尽管该字段由进程本身和其他正在寻找其子进程的进程读取。wait_lock的目的是当wait休眠等待任何子进程退出时充当条件锁。一个正在退出的子进程持有wait_lockp->lock直到它将其状态设置为ZOMBIE,唤醒其父进程,并让出CPU。wait_lock还序列化了父进程和子进程并发的exit,以便init进程(继承了子进程)保证从其wait中被唤醒。wait_lock是一个全局锁而不是每个父进程的锁,因为,在一个进程获取它之前,它无法知道它的父进程是谁。