首页 文章

来自linux内核的schedule()switch_to()函数如何实际工作?

提问于
浏览
27

我试图了解linux内核中的调度过程是如何工作的 . 我的问题不是调度算法 . 它的功能 schedule()switch_to() 如何工作 .

我会试着解释一下 . 我看到了:

当进程耗尽时间片时,标志 need_reschedscheduler_tick() 设置 . 内核检查标志,看到它已设置,并调用 schedule() (与问题1相关)切换到新进程 . 此标志是一个消息,应该尽快调用调度,因为另一个进程应该运行 . 返回用户空间或从中断返回后,将检查 need_resched 标志 . 如果已设置,则内核会在继续之前调用调度程序 .

查看内核源代码(linux-2.6.10 - 本书"Linux Kernel Development, second edition"所基于的版本),我还看到一些代码可以自动调用 schedule() 函数,让另一个进程有权运行 . 我看到函数 switch_to() 是实际执行上下文切换的函数 . 我研究了一些与架构相关的代码,试图理解 switch_to() 实际上在做什么 .

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

  • switch_to() 完成时,当前正在运行的进程是什么?调用 schedule() 的过程?或者下一个过程,那个被选中运行的过程?

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

  • 如果无法从中断调用 schedule() 函数,则何时设置标志 need_resched

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

我不知道我是否能说清楚自己 . 如果我不能,我希望我可以在一些答案(或问题)之后做到这一点 . 我已经看过几个试图了解这个过程的消息来源 . 我有一本书“Linux Kernel Development,sec ed”,我也在使用它 . 我对MIP和H8300架构有所了解,如果有帮助可以解释一下 .

1 回答

  • 29
    • 调用switch_to()后,内核堆栈切换到 next 中指定的任务的内核堆栈 . 更改地址空间等在例如context_switch().中处理

    • schedule() 无法在原子上下文中调用,包括来自中断(请参阅schedule_debug()中的检查) . 如果需要重新安排,则设置TIF_NEED_RESCHED任务标志,该标志在interrupt return path中检查 .

    • 见2 .

    • 我相信,使用默认的8K堆栈,可以使用当前正在执行的任何内核堆栈来处理中断 . 如果使用4K堆栈,我相信's a separate interrupt stack (automatically loaded thanks to some x86 magic), but I' m在这一点上并不完全确定 .

    更详细一点,这是一个实际的例子:

    至于 switch_to() ; switch_to() (在x86-32上)的作用是:

    • 保存EIP(指令指针)和ESP(堆栈指针)的当前值,以便稍后返回此任务 .

    • 切换 current_task 的值 . 此时, current 现在指向新任务 .

    • 切换到新堆栈,然后将我们切换的任务保存的EIP推送到堆栈 . 之后,将使用此EIP作为返回地址执行返回;这是它如何跳回到以前称为 switch_to() 的旧代码

    • 致电__switch_to() . 此时, current 指向新的任务,我们're on the new task'的堆栈,但各种其他CPU状态尚未更新 . __switch_to() 处理切换FPU,段描述符,调试寄存器等事物的状态 .

    • __switch_to() 返回后,将返回 switch_to() 手动推入堆栈的返回地址,将执行返回到新任务中 switch_to() 之前的位置 . 现在,切换到任务已完全恢复执行 .

    x86-64非常相似,但由于ABI不同,必须稍微保存/恢复状态 .

相关问题