linux调度程序是否需要进行上下文切换?

时间:2012-05-31 18:07:39

标签: linux linux-kernel kernel

我有一个关于linux调度程序和其他类似内核系统调用的一般性问题。

linux调度程序是否被视为“进程”,并且对调度程序的每次调用都需要上下文切换,就像它只是另一个进程一样?

假设我们有一个时钟标记,它会中断当前正在运行的用户模式进程,现在我们必须调用调度程序。对调度程序本身的调用是否会引发上下文切换?调度程序是否有自己的一组寄存器和U区域以及每次调用时必须恢复的内容?

上述问题适用于许多其他系统调用。内核进程在上下文切换方面的行为类似于常规进程,唯一的区别是它们拥有更多权限并可以访问cpu吗?

我问这个,因为上下文切换开销很昂贵。调用调度程序本身会激发上下文切换以恢复调度程序状态听起来很奇怪,之后调度程序调用另一个进程来运行并再次调用另一个上下文切换。

3 个答案:

答案 0 :(得分:5)

这是一个非常好的问题,除了硬件知道操作系统和任务调度程序的概念之外,答案是肯定的。

在硬件中,您会发现限制为“超级用户”模式的寄存器。没有详细介绍内部CPU架构,有“用户模式”和“管理员模式”的基本程序执行寄存器的副本,后者只能由操作系统本身访问(通过标记在内核设置的控制寄存器,表示内核或用户模式应用程序当前是否正在运行。

所以你说的“上下文切换”是交换/重置用户模式寄存器(指令寄存器,堆栈指针寄存器等)等的过程,但是系统寄存器没有需要换掉,因为它们与用户分开存放。

例如,x86中的用户模式堆栈是USP-A7,而管理程序模式堆栈是SSP-A7。因此内核本身(包含任务调度程序)将使用管理程序模式堆栈和其他管理程序模式寄存器来运行自身,在运行时将管理程序模式标志设置为1,然后在用户模式硬件上执行上下文切换 在应用程序之间交换并将超级用户模式标志设置为0。

但在操作系统和任务调度的概念之前,如果您想要执行多任务系统,那么您必须使用您在问题中概述的基本概念:使用硬件中断每次调用任务调度程序x循环,然后换出任务调度程序的应用程序,然后交换新的应用程序。但在大多数情况下,定时器中断本身就是您的实际任务调度程序,并且它将进行大量优化,以减少上下文切换和更多简单的中断处理程序例程。

答案 1 :(得分:1)

实际上,您可以在schedule()中查看kernel/sched.c功能的代码。它写得非常好,应该回答你的大部分问题。

但最重要的是,通过调用schedule()来调用Linux调度程序,schedule()使用其调用者的上下文来完成工作。因此,没有专门的“调度程序”过程。这实际上会使事情变得更加困难 - 如果调度程序是一个进程,它也必须自己安排!

当显式调用schedule()时,它只是将调用者线程A的上下文切换为所选的可运行线程B的上下文,例如它将返回到B(通过恢复寄存器值和堆栈指针,返回{{1}}的地址将成为B而不是A)。

答案 2 :(得分:1)

这是尝试简单描述调度员调用期间发生的事情:

  1. 当前具有上下文的程序正在处理器上运行。寄存器,程序计数器,标志,堆栈基础等都适用于该程序;除了操作系统原生的“保留寄存器”或其他类似情况外,程序中没有任何关于调度程序的信息。
  2. 触发调度程序功能的定时中断。此时发生的唯一事情(在vanilla架构案例中)是程序计数器立即跳转到BIOS中断中列出的任何PC地址。这开始执行调度程序的“dispatch”子程序;其他所有内容都保持不变,因此调度程序会查看以前执行的程序的寄存器,堆栈等。
  3. 调度程序(与所有程序一样)具有一组在当前寄存器集上运行的指令。这些指令的编写方式使得它们知道先前正在执行的应用程序已经将其所有状态都置于其后。调度程序中的前几条指令会将此状态存储在内存中。
  4. 调度程序确定下一个拥有cpu的程序应该是什么,获取所有先前存储的状态并用它填充寄存器。
  5. 调度程序跳转到现在在cpu上建立完整上下文的任务中列出的相应PC计数器。
  6. To(over)简化总结;调度程序不需要寄存器,只需将当前的cpu状态写入预定的内存位置,从预定的内存位置加载另一个进程的cpu状态,然后跳转到该进程停止的位置。