ELF二进制文件中默认信号处理程序的代码在哪里?

时间:2015-09-17 08:37:02

标签: c linux kernel signals

我知道当我们按Ctrl + C时,会引发一个SIGINT信号,终止进程的默认动作将由内核完成。但是这个终止的代码来自哪里?它是在ELF二进制文件中还是内核为我们做的?我认为它在内核中,这就是为什么我们需要在源代码中使用自定义处理程序来覆盖信号行为。

任何指针都会非常感激。

2 个答案:

答案 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                  */

http://lxr.free-electrons.com/source/kernel/signal.c#L2330

答案 1 :(得分:2)

让我们说你kill(theShell, SIGINT)。会发生什么事情......(不显示内核代码,因为它实际上并不相关)

  1. C运行时库将获取系统调用sys_kill()的所有参数,然后继续执行执行原始系统调用的汇编代码。
  2. 内核接收参数,执行权限检查等等......
  3. 如果进程将相应的信号处理程序设置为SIG_DEF,则内核直接执行相应的默认操作并返回。如果进程将相应的信号处理程序设置为SIG_IGN,则忽略该信号并返回系统调用。否则,继续。
  4. 信号被放置在目标进程的信号队列中,以及一些信息,例如发送者。
  5. 一旦目标进程中的一个线程可以选择接收信号,并且没有屏蔽它,就会保存线程的上下文(CPU寄存器,堆栈指针等)并调用信号处理程序。如果线程在信号到达时处于系统调用中,则系统调用返回-EINTR(为简单起见)并调用处理程序。处理程序返回后,将自动调用系统调用sys_sigreturn,在信号之前恢复线程的状态。
  6. 同时执行步骤5kill()进程的系统调用返回。