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