Operating system XV6在调度程序中锁定进程表

Operating system XV6在调度程序中锁定进程表,operating-system,xv6,Operating System,Xv6,下面的函数(yield()from proc.c)中使用的ptable上的锁与获取和释放相关,我对此感到困惑 我的指导老师说,获得state=RUNNABLE; sched(); 释放(&ptable.lock); } > P>让我们考虑2个过程P1和P2。P2已经屈服,现在你在P1 现在在P1内部调用yield()。让我们以此作为你上述的出发点。 在获取ptable.lock后,从yield()调用sched(),在sched()中,您会发现以下语句: swtch(&p->context,m

下面的函数(
yield()
from proc.c)中使用的ptable上的锁与获取和释放相关,我对此感到困惑

我的指导老师说,获得
上的锁是为了避免与可能同时访问
ptable
的其他CPU发生争用情况,但我不明白为什么锁只在最后才释放

这难道不意味着在释放锁之前,新进程将在其整个时间段内运行,其他CPU可以使用ptable

无效收益率(void)
{
获取(&ptable.lock);
cp->state=RUNNABLE;
sched();
释放(&ptable.lock);
}

<代码> > P>让我们考虑2个过程P1和P2。P2已经屈服,现在你在P1

现在在P1内部调用yield()。让我们以此作为你上述的出发点。 在获取
ptable.lock
后,从
yield()
调用
sched()
,在
sched()
中,您会发现以下语句:

swtch(&p->context,mycpu()->scheduler)

这将从当前进程的上下文切换到调度程序上下文。 当我这么说时,所发生的是它将从下面的
switchkvm()
内部
scheduler()

正如您在
ptable.lock
被释放后看到的那样。接下来它将找到一个
RUNNABLE
进程并切换到它。因此,在切换过程中,下面
scheduler()
中的执行一直发生,直到调用
swtch(&(c->scheduler),p->context)

每当P2让步时,它将使用ptable.lock并调用sched()。在sched()内部,将调用swtch并切换到scheduler()的上下文。在scheduler()中,它将从switchkvm()开始

因此在
yield()
内的进程上下文中获取的
ptable.lock
scheduler()内释放

请原谅我的英语。我不是以英语为母语的人

下面是来自的代码片段

void
调度程序(无效)
{
结构程序*p;
结构cpu*c=mycpu();
c->proc=0;
对于(;;){
//在此处理器上启用中断。
sti();
//在进程表上循环查找要运行的进程。
获取(&ptable.lock);
对于(p=ptable.proc;p<&ptable.proc[NPROC];p++){
如果(p->state!=RUNNABLE)
继续;
//切换到所选流程。这是流程的工作
//释放ptable.lock,然后重新获取它
//在跳回到我们身边之前。
c->proc=p;
uvm(p);
p->状态=运行;
swtch(&(c->scheduler),p->context);
//------------------------------------------------------------------------------
//这是上下文切换继续的地方。
switchkvm();
//进程现在已经运行完毕。
//它应该在返回之前更改其p->状态。
c->proc=0;
}
释放(&ptable.lock);
}
}

<代码> > P>让我们考虑2个过程P1和P2。P2已经屈服,现在你在P1

现在在P1内部调用yield()。让我们以此作为你上述的出发点。 在获取
ptable.lock
后,从
yield()
调用
sched()
,在
sched()
中,您会发现以下语句:

swtch(&p->context,mycpu()->scheduler)

这将从当前进程的上下文切换到调度程序上下文。 当我这么说时,所发生的是它将从下面的
switchkvm()
内部
scheduler()

正如您在
ptable.lock
被释放后看到的那样。接下来它将找到一个
RUNNABLE
进程并切换到它。因此,在切换过程中,下面
scheduler()
中的执行一直发生,直到调用
swtch(&(c->scheduler),p->context)

每当P2让步时,它将使用ptable.lock并调用sched()。在sched()内部,将调用swtch并切换到scheduler()的上下文。在scheduler()中,它将从switchkvm()开始

因此在
yield()
内的进程上下文中获取的
ptable.lock
scheduler()内释放

请原谅我的英语。我不是以英语为母语的人

下面是来自的代码片段

void
调度程序(无效)
{
结构程序*p;
结构cpu*c=mycpu();
c->proc=0;
对于(;;){
//在此处理器上启用中断。
sti();
//在进程表上循环查找要运行的进程。
获取(&ptable.lock);
对于(p=ptable.proc;p<&ptable.proc[NPROC];p++){
如果(p->state!=RUNNABLE)
继续;
//切换到所选流程。这是流程的工作
//释放ptable.lock,然后重新获取它
//在跳回到我们身边之前。
c->proc=p;
uvm(p);
p->状态=运行;
swtch(&(c->scheduler),p->context);
//------------------------------------------------------------------------------
//这是上下文切换继续的地方。
switchkvm();
//进程现在已经运行完毕。
//它应该在返回之前更改其p->状态。
c->proc=0;
}
释放(&ptable.lock);
}
}
void
scheduler(void)
{
  struct proc *p;
  struct cpu *c = mycpu();
  c->proc = 0;
  
  for(;;){
    // Enable interrupts on this processor.
    sti();

    // Loop over process table looking for process to run.
    acquire(&ptable.lock);
    for(p = ptable.proc; p < &ptable.proc[NPROC]; p++){
      if(p->state != RUNNABLE)
        continue;

      // Switch to chosen process.  It is the process's job
      // to release ptable.lock and then reacquire it
      // before jumping back to us.
      c->proc = p;
      switchuvm(p);
      p->state = RUNNING;

      swtch(&(c->scheduler), p->context);
//------------------------------------------------------------------------------
// This is where a context switch continues from.
      switchkvm();

      // Process is done running for now.
      // It should have changed its p->state before coming back.
      c->proc = 0;
    }
    release(&ptable.lock);

  }
}