当进程在定时器中断之前退出时,如何在linux内核中进行上下文切换?
我知道如果进程正在运行并且发生定时器中断,那么如果设置了标志,则会自动调用 schedule 函数,schedule函数然后选择要运行的下一个进程 . 基本上在这种情况下,调度函数在当前进程的上下文中运行,但是当进程在计时器中断之前退出时会发生什么?谁在这种情况下调用 schedule 函数?它在什么背景下运行?
schedule
重要的是要理解定时器中断只是为什么 schedule 可能被调用的几百个不同原因之一 . 只有运行时由计算主导的程序,这比程序运行只有几微秒更常见 - 是,微秒 - 一次,系统调用之间"blocking",等待用户输入或者其他什么 .
当进程以任何方式退出时,最终会在该进程的(内核)上下文中调用do_exit . do_exit 调用schedule作为其最后一个操作, schedule 永远不会返回到该上下文 . 注意,在 do_exit 的最后,有一个对 schedule 的调用,紧接着 BUG(); 和一个无限循环 .
do_exit
BUG();
就在此之前, do_exit 调用 exit_notify ,它负责将 SIGCHLD 发送到父进程和/或从调用 wait 释放它 . 因此,很多时候,当调用 schedule 时,父进程将准备好运行,并且将被选中 .
exit_notify
SIGCHLD
wait
do_exit 还释放所有用户空间状态和与进程关联的大部分内核状态,释放内存,关闭文件描述符等 . task_struct 本身必须存活,直到有人调用 wait ,我无法确切知道如何kernel决定现在可以解除分配;这段代码太复杂了 .
task_struct
如果进程调用_exit,则内核调用链只是sys_exit_group到 do_group_exit 到 do_exit . 如果它采用致命的同步信号(例如 SIGSEGV ),则呼叫链会更长,并且在其中有一个棘手的转移 . 硬件陷阱由特定于体系结构的代码(例如x86 do_trap)到 force_sig_info 和 send_signal 到complete_signal进行调整,它调整任务状态,然后告诉调度程序唤醒有问题的进程 . 令人讨厌的进程醒来,特定于体系结构的信号处理逻辑的迷宫最终将其传递给get_signal,其调用 do_group_exit ,其调用 do_exit . 致命的异步信号(例如,在shell提示符下键入 kill 12345 )从sys_kill开始,经过 kill_something_info , group_send_sig_info , do_send_sig_info 到 send_signal ,之后一切都按上述步骤进行 . 在这两种情况下,直到 complete_signal 的所有步骤都可能发生在任何进程上下文中,但是"The offending process wakes up"之后的所有步骤都发生在该进程的上下文中 .
do_group_exit
SIGSEGV
force_sig_info
send_signal
kill 12345
kill_something_info
group_send_sig_info
do_send_sig_info
complete_signal
本说明中仅特定于Linux的部分是内核's code. Any implementation of Unix will have kernel functions that do more or less what Linux' s do_exit 和 schedule do中的函数名称,并且涉及部署 _exit ,致命同步信号和致命异步信号的操作序列将是可识别的类似 .
_exit
1 回答
重要的是要理解定时器中断只是为什么
schedule
可能被调用的几百个不同原因之一 . 只有运行时由计算主导的程序,这比程序运行只有几微秒更常见 - 是,微秒 - 一次,系统调用之间"blocking",等待用户输入或者其他什么 .当进程以任何方式退出时,最终会在该进程的(内核)上下文中调用do_exit .
do_exit
调用schedule作为其最后一个操作,schedule
永远不会返回到该上下文 . 注意,在do_exit
的最后,有一个对schedule
的调用,紧接着BUG();
和一个无限循环 .就在此之前,
do_exit
调用exit_notify
,它负责将SIGCHLD
发送到父进程和/或从调用wait
释放它 . 因此,很多时候,当调用schedule
时,父进程将准备好运行,并且将被选中 .do_exit
还释放所有用户空间状态和与进程关联的大部分内核状态,释放内存,关闭文件描述符等 .task_struct
本身必须存活,直到有人调用wait
,我无法确切知道如何kernel决定现在可以解除分配;这段代码太复杂了 .如果进程调用_exit,则内核调用链只是sys_exit_group到
do_group_exit
到do_exit
. 如果它采用致命的同步信号(例如SIGSEGV
),则呼叫链会更长,并且在其中有一个棘手的转移 . 硬件陷阱由特定于体系结构的代码(例如x86 do_trap)到force_sig_info
和send_signal
到complete_signal进行调整,它调整任务状态,然后告诉调度程序唤醒有问题的进程 . 令人讨厌的进程醒来,特定于体系结构的信号处理逻辑的迷宫最终将其传递给get_signal,其调用do_group_exit
,其调用do_exit
. 致命的异步信号(例如,在shell提示符下键入kill 12345
)从sys_kill开始,经过kill_something_info
,group_send_sig_info
,do_send_sig_info
到send_signal
,之后一切都按上述步骤进行 . 在这两种情况下,直到complete_signal
的所有步骤都可能发生在任何进程上下文中,但是"The offending process wakes up"之后的所有步骤都发生在该进程的上下文中 .本说明中仅特定于Linux的部分是内核's code. Any implementation of Unix will have kernel functions that do more or less what Linux' s
do_exit
和schedule
do中的函数名称,并且涉及部署_exit
,致命同步信号和致命异步信号的操作序列将是可识别的类似 .