Linux 内核中的 Schedule()+switch_to() 函数实际上是如何工作的?
我试图了解 Linux 内核中的调度过程实际上是如何工作的。我的问题不是关于调度算法。它是关于函数 schedule()
和 switch_to()
如何工作的。
我会尝试解释一下。我看到:
当进程用完时间片时,标志 need_resched
由 scheduler_tick()
设置。内核检查该标志,发现它已设置,然后调用 schedule()
(与问题 1 相关)以切换到新进程。该标志是一条消息,表明应尽快调用调度,因为另一个进程需要运行。 返回用户空间或从中断返回后,将检查 need_resched
标志。如果设置了,内核会在继续之前调用调度程序。
查看内核源码(linux-2.6.10 - 《Linux Kernel Development,第二版》一书所基于的版本),我还看到一些代码可以自动调用 schedule()
函数,赋予另一个进程运行权。 我看到函数 switch_to()
是实际执行上下文切换的函数。我研究了一些与架构相关的代码,试图了解 switch_to()
实际在做什么。
这种行为引发了一些我找不到答案的问题:
当
switch_to()
完成时,当前正在运行的进程是什么?调用schedule()
的进程?或者下一个进程,即被选择运行的进程?当
schedule()
被中断调用时,选定的要运行的进程会在中断处理完成时开始运行(在某种 RTE 之后)?或者在那之前?如果
schedule()
函数无法从中断中调用,那么标志 -need_resched
何时设置?当定时器中断处理程序工作时,使用什么堆栈?
我不知道我是否可以说清楚。如果我不能,我希望在回答(或问题)后我可以做到这一点。 我已经查看了几个来源,试图理解这个过程。我有《Linux Kernel Development, sec ed》一书,我也在使用它。 我对 MIP 和 H8300 架构有所了解,如果这有助于解释的话。
I'm trying to understand how the schedule process in linux kernel actually works. My question is not about the scheduling algorithm. Its about how the functions schedule()
and switch_to()
work.
I'll try to explain. I saw that:
When a process runs out of time-slice, the flag need_resched
is set by scheduler_tick()
. The kernel checks the flag, sees that it is set, and calls schedule()
(pertinent to question 1) to switch to a new process. This flag is a message that schedule should be invoked as soon as possible because another process deserves to run.
Upon returning to user-space or returning from an interrupt, the need_resched
flag is checked. If it is set, the kernel invokes the scheduler before continuing.
Looking into the kernel source (linux-2.6.10 - version that the book "Linux Kernel Development, second edition" is based on), I also saw that some codes can call the schedule()
function voluntarily, giving another process the right to run.
I saw that the function switch_to()
is the one that actually does the context switch. I looked into some architecture dependent codes, trying to understand what switch_to()
was actually doing.
That behavior raised some questions that I could not find the answers for :
When
switch_to()
finishes, what is the current running process? The process that calledschedule()
? Or the next process, the one that was picked to run?When
schedule()
gets called by an interrupt, the selected process to run starts to run when the interrupt handling finishes (after some kind of RTE) ? Or before that?If the
schedule()
function can not be called from an interrupt, when is the flag-need_resched
set?When the timer interrupt handler is working, what stack is being used?
I don't know if I could make myself clear. If I couldn't, I hope I can do this after some answers (or questions).
I already looked at several sources trying to understand that process. I have the book "Linux Kernel Development, sec ed", and I'm using it too.
I know a bit about MIPs and H8300 architecture, if that help to explain.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
switch_to()< 后/code>
,内核堆栈切换到
next
中指定的任务的内核堆栈。更改地址空间等在context_switch 中处理()
.schedule()
不能在原子上下文中调用,包括从中断中调用(请参阅schedule_debug()
)。如果需要重新安排,则设置 TIF_NEED_RESCHED 任务标志,该标志在 中断返回路径。更详细一点,这里有一个实际的例子:
schedule()
时短暂启用中断。schedule()
)以及检查挂起的信号,然后返回retint_check
直到没有设置更重要的标志。至于
switch_to()
; switch_to()(在 x86-32 上)的作用是:current_task
的值。此时,current
现在指向新任务。switch_to()
的旧代码的current
指向新任务,并且我们位于新任务的堆栈上,但各种其他 CPU 状态尚未更新。__switch_to()
处理 FPU、段描述符、调试寄存器等状态的切换。__switch_to()
返回时,switch_to 的返回地址返回到手动压入堆栈的 ()
,将执行放回新任务中switch_to()
之前的位置。现在已完全恢复切换到的任务的执行。x86-64 非常相似,但由于 ABI 不同,必须稍微多做一些状态保存/恢复操作。
switch_to()
, the kernel stack is switched to that of the task named innext
. Changing the address space, etc, is handled in egcontext_switch()
.schedule()
cannot be called in atomic context, including from an interrupt (see the check inschedule_debug()
). If a reschedule is needed, the TIF_NEED_RESCHED task flag is set, which is checked in the interrupt return path.To be a bit more detailed, here's a practical example:
schedule()
.schedule()
if needed) as well as checking for pending signals, then goes back for another round atretint_check
until there's no more important flags set.As for
switch_to()
; whatswitch_to()
(on x86-32) does is:current_task
. At this point,current
now points to the new task.switch_to()
current
points to the new task, and we're on the new task's stack, but various other CPU state hasn't been updated.__switch_to()
handles switching the state of things like the FPU, segment descriptors, debug registers, etc.__switch_to()
, the return address thatswitch_to()
manually pushed onto the stack is returned to, placing execution back where it was prior to theswitch_to()
in the new task. Execution has now fully resumed on the switched-to task.x86-64 is very similar, but has to do slightly more saving/restoration of state due to the different ABI.