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