我知道当我们按Ctrl + C时,会引发一个SIGINT信号,终止进程的默认动作将由内核完成。但是这个终止的代码来自哪里?它是在ELF二进制文件中还是内核为我们做的?我认为它在内核中,这就是为什么我们需要在源代码中使用自定义处理程序来覆盖信号行为。
任何指针都会非常感激。
答案 0 :(得分:5)
这是内核为我们做的事情。您可以通过阅读内核源代码中的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
)如果不是"默认" handler(SIG_DEF
),内核只会将其标记为正在运行(并且取决于它是否一次性将处理程序再次移动到默认处理程序)。
但是,如果没有注册信号处理程序,或者它是SIG_DEF
,内核会检查是否需要暂停进程,最后内核会说明以下内容:
2330 /*
2331 * Anything else is fatal, maybe with a core dump.
2332 */
答案 1 :(得分:2)
让我们说你kill(theShell, SIGINT)
。会发生什么事情......(不显示内核代码,因为它实际上并不相关)
sys_kill()
的所有参数,然后继续执行执行原始系统调用的汇编代码。SIG_DEF
,则内核直接执行相应的默认操作并返回。如果进程将相应的信号处理程序设置为SIG_IGN
,则忽略该信号并返回系统调用。否则,继续。-EINTR
(为简单起见)并调用处理程序。处理程序返回后,将自动调用系统调用sys_sigreturn
,在信号之前恢复线程的状态。5
,kill()
进程的系统调用返回。