当进程在定时器中断之前退出时,如何在linux内核中进行上下文切换?
我知道如果进程正在运行并且发生定时器中断,那么如果设置了标志,则自动调用schedule
函数,schedule函数然后选择要运行的下一个进程。基本上在这种情况下,调度函数在当前进程的上下文中运行,但是当进程在计时器中断之前退出时会发生什么?谁在这种情况下调用schedule
函数?它在什么情况下运行?
答案 0 :(得分:4)
了解计时器中断只是为什么schedule
可能被调用的几百个不同原因中的一个,这一点非常重要。只有那些运行时由计算占主导地位的程序才会耗尽它们的时间片,而这些程序比你想象的要少。对于程序来说,只运行几微秒(是的,微秒),在一段时间内,在阻塞"之间运行的情况更为常见。在系统调用中,等待用户输入或其他任何内容。
当一个进程以任何方式退出时,最终会在该进程的(内核)上下文中调用do_exit
。 do_exit
将schedule
作为最后一次操作,schedule
永远不会返回该上下文。请注意,在do_exit
的最后,有schedule
的来电,紧接着是BUG();
和无限循环。
在此之前,do_exit
调用exit_notify
,负责将SIGCHLD
发送到父进程和/或通过调用wait
将其释放。因此,很多时候,父进程将在schedule
被调用时准备好运行,并将被选中。
do_exit
还释放所有用户空间状态和与进程关联的大部分内核状态,释放内存,关闭文件描述符等。task_struct
本身必须存在,直到有人调用{ {1}},我无法确切知道内核如何确定它现在可以解除分配;这段代码太复杂了。
如果进程调用_exit
,则内核调用链只是sys_exit_group
到wait
到do_group_exit
。如果它采用致命的同步信号(例如do_exit
),则呼叫链会更长并且在其中具有棘手的转移。硬件陷阱由特定于体系结构的代码(例如x86 do_trap
)通过SIGSEGV
和force_sig_info
到complete_signal
进行调整,调整任务状态然后告知调度程序唤醒违规过程。令人讨厌的进程醒来,特定于体系结构的信号处理逻辑迷宫最终将其传递给get_signal
,调用send_signal
,调用do_group_exit
。致命异步信号(例如,在shell提示符下输入do_exit
)从sys_kill
开始,然后通过kill 12345
,kill_something_info
,{{1} } group_send_sig_info
,然后一切按上述步骤进行。在这两种情况下,do_send_sig_info
之前的所有步骤都可能发生在任何进程上下文中,但是在"违规进程唤醒之后的所有内容都会被唤醒。发生在该过程的背景下。
本说明中仅特定于Linux的部分是内核代码中的函数名称。 Unix的任何实现都将具有内核函数,这些函数或多或少地执行Linux send_signal
和complete_signal
所做的事情,以及涉及部署do_exit
致命同步信号的操作序列,和致命的异步信号将是可识别的相似。