我知道当我们按下Ctrl+C时,会引发一个SIGINT信号,内核会执行默认的终止进程操作。但是这个终止代码是从哪里来的呢?它在ELF二进制文件中吗?还是内核为我们执行了这个操作?我认为这个终止代码在内核中,这也是为什么我们需要在源代码中设置自定义处理程序来覆盖信号行为的原因。
如果有相关指针,将不胜感激。
如果有相关指针,将不胜感激。
这是内核为我们做的事情。您可以通过阅读内核源代码中的signal.c
文件找到所有信息。
内核尝试查找已注册信号处理程序的位置从这里开始:http://lxr.free-electrons.com/source/kernel/signal.c#L2257
2257 ka = &sighand->action[signr-1];
2258
2259 /* Trace actually delivered signals. */
2260 trace_signal_deliver(signr, &ksig->info, ka);
2261
2262 if (ka->sa.sa_handler == SIG_IGN) /* Do nothing. */
2263 continue;
2264 if (ka->sa.sa_handler != SIG_DFL) {
2265 /* Run the handler. */
2266 ksig->ka = *ka;
2267
2268 if (ka->sa.sa_flags & SA_ONESHOT)
2269 ka->sa.sa_handler = SIG_DFL;
2270
2271 break; /* will return non-zero "signr" value */
2272 }
SIG_IGN
),也不是“默认”处理程序(SIG_DEF
),内核将简单地标记它以供运行(并根据其是否为一次性处理程序将处理程序移回默认处理程序)。SIG_DEF
,内核会检查是否需要暂停进程,最后内核会声明以下内容:2330 /*
2331 * Anything else is fatal, maybe with a core dump.
2332 */
kill(theShell, SIGINT)
。发生的事情类似于以下过程...(不显示内核代码,因为实际上与此无关)
sys_kill()
的参数,并执行执行原始系统调用的汇编代码。SIG_DEF
,内核将直接执行相应的默认动作并返回。如果进程将相应的信号处理程序设置为 SIG_IGN
,则忽略该信号并返回系统调用。否则,继续执行。-EINTR
(出于简单起见),然后调用处理程序。处理程序返回后,自动调用系统调用 sys_sigreturn
,将线程状态恢复到信号前的状态。kill()
进程的系统调用返回。