Linux kernel schedule()和#x2B;将linux内核中的函数切换到()实际工作吗?

Linux kernel schedule()和#x2B;将linux内核中的函数切换到()实际工作吗?,linux-kernel,context-switch,Linux Kernel,Context Switch,我试图理解linux内核中的调度过程实际上是如何工作的。我的问题不是关于调度算法。这是关于函数schedule()和如何切换到() 我会尽力解释的。我看到: 当进程的时间片用完时,调度程序_tick()会设置标志是否需要重新调度。内核检查标志,查看它是否已设置,并调用schedule()(与问题1相关)以切换到新进程。此标志是一条消息,表示应尽快调用调度,因为另一个进程值得运行。 在返回到用户空间或从中断返回时,检查need\u resched标志。如果设置了,内核将在继续之前调用调度程序 查看

我试图理解linux内核中的调度过程实际上是如何工作的。我的问题不是关于调度算法。这是关于函数
schedule()
如何切换到()

我会尽力解释的。我看到:

当进程的时间片用完时,
调度程序_tick()
会设置标志
是否需要重新调度
。内核检查标志,查看它是否已设置,并调用
schedule()
(与问题1相关)以切换到新进程。此标志是一条消息,表示应尽快调用调度,因为另一个进程值得运行。 在返回到用户空间或从中断返回时,检查
need\u resched
标志。如果设置了,内核将在继续之前调用调度程序

查看内核源代码(“linux内核开发,第二版”一书所基于的linux-2.6.10版本),我还发现一些代码可以自动调用
schedule()
函数,从而赋予另一个进程运行的权利。 我看到函数
switch_to()
实际上是执行上下文切换的函数。我研究了一些与体系结构相关的代码,试图了解
switch\u to()
实际上在做什么

这种行为引发了一些我无法找到答案的问题:

  • 切换到()
    完成时,当前正在运行的进程是什么?调用
    schedule()
    的进程?还是下一个进程,即选择运行的进程

  • 当中断调用
    schedule()
    时,当中断处理完成时(某种RTE之后),要运行的选定进程开始运行?还是在那之前

  • 如果无法从中断调用
    schedule()
    函数,则何时需要重新设置标记-

  • 当定时器中断处理程序工作时,使用什么堆栈

  • 我不知道我是否能说清楚。如果我做不到,我希望在回答了一些问题后我能做到这一点。 我已经查阅了一些资料来源,试图了解这一过程。我有一本书“Linux内核开发,第二版”,我也在使用它。 我对MIPs和H8300架构略知一二,如果这有助于解释的话

  • 调用后,内核堆栈切换到
    next
    中指定的任务的堆栈。更改地址空间等在eg中处理
  • schedule()
    不能在原子上下文中调用,包括从中断调用(请参阅签入)。如果需要重新安排,将设置TIF_NEED_RESCHED任务标志,该标志将在中选中
  • 见第2条
  • 我相信,对于默认的8K堆栈,中断是通过当前正在执行的内核堆栈来处理的。如果使用4K堆栈,我相信会有一个单独的中断堆栈(由于某些x86魔法自动加载),但我不能完全确定这一点
  • 更详细地说,这里有一个实际的例子:

  • 发生中断。CPU切换到一个中断蹦床例程,该例程将中断号推送到堆栈上,然后将jmps推到堆栈上
  • 普通中断调用,然后
  • 在某个时刻,会做出切换任务的决定。这可能是由于计时器中断或唤醒呼叫造成的。在任何一种情况下,都会调用,设置TIF_NEED_RESCHED任务标志
  • 最后,CPU在原始中断中从do_IRQ返回,并继续执行“如果此IRQ是从内核内部调用的,则调用它,如果是调用”,这将在执行
    调度()时短暂启用中断
  • 如果IRQ是从用户空间调用的,我们首先在返回之前调用它。如果是这样,我们转到,它检查挂起的重新调度(并在需要时直接调用
    schedule()
    )以及挂起的信号,然后返回到另一轮,直到没有设置更重要的标志
  • 最后,我们
  • 至于
    切换到()
    切换到()
    (在x86-32上)所做的是:

  • 保存EIP(指令指针)和ESP(堆栈指针)的当前值,以备稍后返回此任务时使用
  • 切换
    当前任务的值
    。此时,
    current
    现在指向新任务
  • 切换到新堆栈,然后将切换到的任务保存的EIP推送到堆栈上。稍后,将使用该EIP作为返回地址执行返回;这就是它如何跳回以前调用的
    switch\u to()
  • 打电话。此时,
    current
    指向新任务,我们在新任务的堆栈上,但其他各种CPU状态尚未更新<代码>\u切换到()
  • 处理FPU、段描述符、调试寄存器等的状态切换
  • \u切换到()
    返回后,手动推送到堆栈上的
    切换到()
    的返回地址将返回,将执行放回新任务中切换到()之前的位置。现在已在切换到的任务上完全恢复执行

  • x86-64非常类似,但由于ABI不同,必须稍微多保存/恢复一些状态。

    对不起,我还是不明白。示例:假设有一个任务“a”正在运行。1-发生计时器中断。2-定时器中断处理程序启动。3-现在是调用schedule()的时候了,我们就这么做了。4-schedule()选择了任务“B”,切换到()已完成,任务“B”是当前任务(现在我们正在使用任务“B”的堆栈,并且仍在运行中断代码)。5-计时器中断完成,并恢复任务“B”的执行。这个例子正确吗?如果不是,这个过程是如何发生的?谢谢你的时间和耐心,但我想我很遗憾