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

8
我知道当我们按下Ctrl+C时,会引发一个SIGINT信号,内核会执行默认的终止进程操作。但是这个终止代码是从哪里来的呢?它在ELF二进制文件中吗?还是内核为我们执行了这个操作?我认为这个终止代码在内核中,这也是为什么我们需要在源代码中设置自定义处理程序来覆盖信号行为的原因。
如果有相关指针,将不胜感激。
2个回答

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),也不是“默认”处理程序(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


更多问题--如果我提供自己的自定义处理程序,谁将执行自定义处理程序中的代码?逻辑将由操作系统在ring 0中执行还是由进程在ring 3中执行? - bawejakunal
1
@bawejakunal:它将在第三特权级运行。否则会成为完全的安全隐患。 - 3442

2
假设你调用了 kill(theShell, SIGINT)。发生的事情类似于以下过程...(不显示内核代码,因为实际上与此无关)
  1. C运行库会获取所有传递给系统调用 sys_kill() 的参数,并执行执行原始系统调用的汇编代码。
  2. 内核接收参数并执行权限检查等操作...
  3. 如果进程将相应的信号处理程序设置为 SIG_DEF,内核将直接执行相应的默认动作并返回。如果进程将相应的信号处理程序设置为 SIG_IGN,则忽略该信号并返回系统调用。否则,继续执行。
  4. 信号以及一些信息(例如发送者)被放置在目标进程的信号队列中。
  5. 一旦目标进程的线程可以接收信号并且没有被屏蔽,线程的上下文(CPU寄存器,堆栈指针等)将被保存,并且将调用信号处理程序。如果线程在信号到达时正在进行系统调用,则系统调用返回 -EINTR(出于简单起见),然后调用处理程序。处理程序返回后,自动调用系统调用 sys_sigreturn,将线程状态恢复到信号前的状态。
  6. 同时发生第5步,kill()进程的系统调用返回。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接