linux调度器是否需要上下文切换?

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

Linux调度程序是否被认为是一个“进程”,调度程序的每个调用都需要一个上下文切换,就像另一个进程一样?

假设我们有一个中断当前正在运行的用户模式进程的时钟节拍,我们现在必须调用调度器。 对调度程序本身的调用是否会激发上下文切换? 调度程序是否有自己的一套寄存器和U域,以及在每次调用时都不得不还原哪些内容?

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

我问这个,因为上下文切换开销很大。 调用调度器本身引发上下文切换来恢复调度器状态听起来很奇怪,然后调度器调用另一个进程运行,再次调用另一个上下文切换。

Solutions Collecting From Web of "linux调度器是否需要上下文切换?"

这是一个非常好的问题,除了硬件意识到操作系统和任务调度程序的概念之外,对它的回答是“是”。

在硬件中,您会发现限制为“主管”模式的寄存器。 在不涉及内部CPU体系结构的细节方面,有一个“用户模式”和“管理员模式”的基本程序执行寄存器的副本,后者只能由操作系统本身访问(通过控制内核设置哪些内核或用户模式应用程序当前正在运行的注册表)。

所以你所说的“上下文切换”是交换/重置用户模式寄存器(指令寄存器,堆栈指针寄存器等)的过程,但是系统寄存器不需要被换出,因为它们被存储除了用户之外。

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

但是在操作系统和任务调度的想法之前,如果你想做一个多任务系统,那么你就不得不使用你在问题中概述的基本概念:使用硬件中断每x个周期调用任务调度器,然后换出任务调度程序的应用程序,然后交换新的应用程序。 但在大多数情况下,定时器中断本身就是您的实际任务调度程序,并且会进行大量优化,使其不必进行上下文切换,也不需要更多简单的中断处理程序。

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

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

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

下面是对调度程序调用过程中的一些简单描述:

  1. 目前具有上下文的程序正在处理器上运行。 程序计数器,标志,堆栈库等都适用于这个程序。 除了操作系统原生的“保留寄存器”或其他类似情况外,程序没有任何关于调度程序的信息。
  2. 调度器功能的定时中断被触发。 在这一点上唯一发生的事情是在程序计数器立即跳转到BIOS中断的PC地址列表中。 这开始执行调度员的“调度”子程序; 其他一切都保持不变,所以调度员看到之前正在执行的程序的寄存器,堆栈等等。
  3. 调度程序(像所有的程序一样)有一组指令在当前的寄存器组上运行。 这些指令是以这样一种方式编写的,即他们知道先前正在执行的应用程序已经将其所有状态都置于后面。 调度程序中的前几条指令将把这个状态存储在内存中。
  4. 调度员确定下一个应该具有这个CPU的程序,把它的所有先前存储的状态和填充寄存器。
  5. 调度器跳转到相应的PC计数器,如同在cpu上建立完整上下文的任务中所列出的那样。

总结(简化) 调度程序不需要寄存器,只需将当前cpu状态写入预定的存储单元,从预定的存储单元加载另一个进程的cpu状态,然后跳转到该进程停止的地方。