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



我对与以下函数中使用的ptable上的锁相关的获取和释放感到困惑( 来自 proc.c 的yield()(。

我的导师说,获取ptable上的锁是为了避免与其他可能同时访问ptable的 CPU 发生争用条件,但我对为什么锁只在这里最后释放感到困惑。

这是否意味着新进程在释放锁之前运行其整个时间片,其他 CPU 可以使用ptable

void yield(void)
{
acquire(&ptable.lock);
cp->state = RUNNABLE;
sched();
release(&ptable.lock);
}

让我们考虑 2 个过程,P1 和 P2。P2已经屈服了,现在你在P1。

现在在 P1 中,你调用 yield((。让我们以此作为您上面的起点。 从获取ptable.lockyield()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.lockscheduler()内部释放。

PS:请原谅我的英语。我不是母语人士。

以下是 https://github.com/mit-pdos/xv6-public/blob/master/proc.c 的代码片段

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);
}
}

最新更新