【问题标题】:I can't understand this line of code in xv6xv6 看不懂这行代码
【发布时间】:2021-08-22 10:44:49
【问题描述】:

尽管查阅了文档,但我仍然无法理解这一行:swtch(&c->scheduler, &p->context);

我的问题:我知道这行是切换p->context,包括保存寄存器和恢复寄存器,但是我看不懂pc这个过程的变化,那这段代码的执行顺序是什么? swtch(&c->scheduler, &p->context);执行后,是不是马上执行c->proc = 0;,那么执行c->proc=p; 的效果就消失了?我现在很困惑。

代码链接:https://github.com/mit-pdos/xv6-riscv/blob/riscv/kernel/proc.c 第 456 行


*// Per-CPU process scheduler.*
*// Each CPU calls scheduler() after setting itself up.*
*// Scheduler never returns.  It loops, doing:*
*//  - choose a process to run.*
*//  - swtch to start running that process.*
*//  - eventually that process transfers control*
*//    via swtch back to the scheduler.*
void
scheduler(void)
{
  struct proc *p;
  struct cpu *c = mycpu();

  c->proc = 0;
  for(;;){
    *// Avoid deadlock by ensuring that devices can interrupt.*
    intr_on();
    int found = 0;
    for(p = proc; p < &proc[NPROC]; p++) {
      acquire(&p->lock);
      if(p->state == RUNNABLE) {
        *// Switch to chosen process.  It is the process's job*
        *// to release its lock and then reacquire it*
        *// before jumping back to us.*
        p->state = RUNNING;
        c->proc = p;
        swtch(&c->scheduler, &p->context);

        *// Process is done running for now.*
        *// It should have changed its p->state before coming back.*
        c->proc = 0;
        found = 1;
      }
      release(&p->lock);
    }
    if(found == 0){
      intr_on();
      asm volatile("wfi");
    }
  }
}

【问题讨论】:

  • 我认为这只是一个糟糕的代码而已。
  • 注意swtch.S,忘记标注了。
  • 你有什么不明白的?
  • @Rchar 看这里,我没时间去搜你看不懂的代码。
  • 这是上下文切换。它调用的函数使用这些参数继续在其他地方运行,在不同的地址和不同的加载寄存器集。这(非常)大致是任何操作系统如何更改当前执行的上下文。

标签: c operating-system riscv xv6


【解决方案1】:

这实际上是一段令人困惑的代码,以至于它的原作者在 cmets 中写下了“你不应该理解这个”,所以不要因为不理解而感到难过。

您可能错过的关键是p-&gt;context 包含一个地址,swtch 用于恢复进程p 的执行。已经设置好了,比如here:

  // Set up new context to start executing at forkret,
  // which returns to user space.
  memset(&p->context, 0, sizeof(p->context));
  p->context.ra = (uint64)forkret;
  p->context.sp = p->kstack + PGSIZE;

因此,当调度程序调用 swtch 时,它实际上是对 p-&gt;context.ra 指向的任何内容进行间接函数调用。该代码将无限期执行,然后最终(某种程度上)返回到 swtch,后者返回到调度程序,并以c-&gt;proc = 0 继续。

(在上面的句子中,“某种”和“有效地”这两个词做了很多工作。要了解这些词背后隐藏的内容,接下来你应该阅读的是coroutines。)

【讨论】:

  • 我知道了。swtch 保存 ra 寄存器,该寄存器保存调用 swtch 的返回地址,然后加载新上下文的 ra。最后是 ret,这里是 ret == jr ra,所以现在 pc 指向新切换进程的某处。
猜你喜欢
  • 2017-05-16
  • 2013-11-01
  • 1970-01-01
  • 1970-01-01
  • 2017-10-13
  • 2023-03-28
  • 1970-01-01
  • 2011-05-10
  • 1970-01-01
相关资源
最近更新 更多