11.6 XV6线程切换 --- yield/sched函数

回到devintr函数返回到usertrap函数中的位置。在gdb里面输入几次step走到yield函数的调用。yield函数是整个线程切换的第一步,下面是yield函数的内容:

yield函数只做了几件事情,它首先获取了进程的锁。实际上,在锁释放之前,进程的状态会变得不一致,例如,yield将要将进程的状态改为RUNABLE,表明进程并没有在运行,但是实际上这个进程还在运行,代码正在当前进程的内核线程中运行。所以这里加锁的目的之一就是:即使我们将进程的状态改为了RUNABLE,其他的CPU核的调度器线程也不可能看到进程的状态为RUNABLE并尝试运行它。否则的话,进程就会在两个CPU核上运行了,而一个进程只有一个栈,这意味着两个CPU核在同一个栈上运行代码(注,因为XV6中一个用户进程只有一个用户线程)。

接下来yield函数中将进程的状态改为RUNABLE。这里的意思是,当前进程要出让CPU,并切换到调度器线程。当前进程的状态是RUNABLE意味着它还会再次运行,因为毕竟现在是一个定时器中断打断了当前正在运行的进程。

之后yield函数中调用了位于proc.c文件中的sched函数。我们进入到sched函数中,

可以看出,sched函数基本没有干任何事情,只是做了一些合理性检查,如果发现异常就panic。为什么会有这么多检查?因为这里的XV6代码已经有很多年的历史了,这些代码经历过各种各样的bug,相应的这里就有各种各样的合理性检查和panic来避免可能的bug。我将跳过所有的检查,直接走到位于底部的swtch函数。

Last updated