在Linux中接收SIGINT和异常处理 [英] Receiving SIGINT and exception Handles in Linux

查看:413
本文介绍了在Linux中接收SIGINT和异常处理的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

假设我们有一个C语言程序,该程序使用sleep()函数

Let's say we have a program in C that uses the sleep() function

程序执行并进入睡眠状态.然后,我们输入 Ctrl + C 向该进程发送SIGINT信号.

The program executes and goes to sleep. Then we type Ctrl+C to send a SIGINT signal to the process.

我们知道接收到SIGINT时的默认操作是终止进程,我们也知道每当睡眠进程接收到信号时,sleep()函数都会恢复该进程.

We know that the default action upon receipt of a SIGINT is to terminate the process, we also know that the sleep() function resume the process whenever the sleeping process receives a signal.

我的教科书上说,为了允许sleep()函数返回,我们必须安装一个SIGINT处理程序,如下所示:

And my textbook says in order to allow sleep() function to return, we must install a SIGINT handler like this:

void handler(int sig){
    return; /* Catch the signal and return */
}
...
int main(int argc, char **argv) {
   ...
   if (signal(SIGINT, handler) == SIG_ERR) /* Install SIGINT handler */
      unix_error("signal error\n");
   ...
   sleep(1000)
}

虽然代码看起来很简单,但是如果我想更深入地研究,我仍然有疑问:

Althouth the code seems to be straightforward, I still have questions if I want to dig deeper:

背景:当进程处于休眠状态时,我们键入 Ctrl + C 发送SIGINT

Background: When the process is sleeping and we type Ctrl+C to send SIGINT

Q1-我的理解是,内核会通过更新pend位向量中SIGINT的对应挂起位来将SIGINT发送到进程,我的理解正确吗?

Q1-My understanding is, Kernel sends SIGINT to the process by updating the SIGINT's corresponging pending bit in the pend bit vector, is my understanding correct?

Q2-处理器检测到SIGINT的存在,但是由于我们覆盖了处理程序以使其返回而不是终止进程,因此我们的处理程序得以执行,然后内核清除了SIGINT的对应挂起位,我的理解正确吗?

Q2-The processor detects the existance of SIGINT, but since we overwrite the handler to make it return in stead of terminating the process, so our handler get executed, and then Kernel clears SIGINT's corresponging pending bit, is my understanding correct?

Q3-由于SIGINT的对应挂起位已清除,那么sleep()函数如何返回?我认为它应该仍然处于睡眠状态,因为从理论上讲,sleep()函数无法知道SIGINT的存在(已被清除)

Q3- Since SIGINT's corresponging pending bit is cleared, then how can sleep() function gets return? I think it should be in sleep still because in theory, sleep() function has no way of knowing the existance of SIGINT(has been cleared)

推荐答案

  • 问题1:内核检查进程是否阻塞了接收到的信号,如果已阻塞,它将更新挂起的信号位(不可靠,在具有可靠信号的系统上,这应该是一个计数器)在流程条目中,用于在再次解除阻止信号时调用信号处理程序(请参见下文).如果未阻止,则系统调用将准备返回值和errno值,并返回到用户模式,并在程序的虚拟堆栈中安装特殊代码,从而使该代码在从泛型返回之前调用信号处理程序(已在用户模式下). syscall代码.系统调用的返回将-1赋予调用者代码,并且errno变量设置为EINTR.这要求该进程已安装信号处理程序,因为默认情况下该操作是中止该进程,因此它不会从正在等待的系统调用中返回.想一想,当说出"内核"时,实际执行的代码在系统调用中被唤醒,并被告知特殊情况(接收到信号).中断的调用检测到要调用信号处理程序,并准备从syscall()包装返回之前,用户堆栈跳到正确的位置(用户代码中的中断处理程序).

    • Q1: the kernel checks if the process has blocked the received signal, if so, it updates the pending signal bit (unreliable, on systems with relable signals, this should be a counter) in the process entry, for the signal handler to be called when signals are unblocked again (see below). If not blocked, the system call prepares the return value and errno value and returns to user mode with a special code installed in the program's virtual stack that makes it to call the signal handler (already in user mode) before returning from the generic syscall code. The return from the system call gives -1 to the caller code, and the errno variable is set to EINTR. This requires the process to have installed a signal handler, because by default the action is to abort the process, so it will not return from the system call it is waiting on. Think that when one says the kernel the actual code executed is in the system call being awaken and notified of the special condition (a signal received) The interrupted call, detects that a signal handler is to be called, and prepares the user stack to jump to the proper place (the interrupt handler in user code) before returning from the syscall() wrapper.

      Q2:未决位仅用于保存要调用未决信号处理程序的 ,因此不是这种情况.在该过程的执行部分中,unix程序加载器在从系统调用返回之前,安装一些基本代码以跳转到信号处理程序.这是因为信号处理程序必须在用户模式下执行(而不是在内核模式下执行),所以一切都会在系统调用终止时发生.执行的信号处理程序是SIGINT,但是被中断的代码是系统调用,直到系统调用返回(返回代码和errno变量已固定)之后,什么也不会发生.

      Q2: pending bit is only used to save that a pending signal handler is to be called, so this is not the case. In the execution part of the process, the unix program loader installs some basic code to jump to the signal handler before returning from the system call. This is because the signal handler has to execute in user mode (not in kernel mode) so everything happens upon termination of system call. The signal handler executed is the SIGINT, but the code interrupted is a system call, and nothing happens until the system call returns (with the return code and the errno variable already fixed)

      问题3:好吧,您的推理基于错误的前提,即中断待处理标志表示已接收到中断.此位表示已取消阻塞后立即将未处理的中断标记为要发送,并且仅在另一个系统调用(取消阻塞信号)中发生.一旦信号被解除阻塞,sigsetmask(2) syscall的返回代码将执行信号处理程序.在这种情况下,信号将在计时器经过后立即传递到进程,系统调用将被中断,并且,如果您尚未为SIGALRM信号安装信号处理程序(但是sleep(2)实现会执行此操作- -至少是旧的实现)程序将被中止.

      Q3: well, your reasoning was based on a wrong premise, that is, the interrupt pending flag is indicating that an interrupt has been received. This bit only signals that an unprocessed interrupt has been marked for delivery as soon as you unblock it, and this only happens in another system call (to unblock a signal). As soon as the signal is unblocked, the return code of the sigsetmask(2) syscall will execute the signal handler. In this case, the signal will be delivered to the process as soon as the timer elapses, the system call will be interrupted and, if you have not installed a signal handler for the SIGALRM signal (but sleep(2) implementation does this ---at least, old implementations did) the program will be aborted.

      当我说程序被内核中止时,但在两种情况下,所涉及的信号(SIGINTSIGALRM)都不会使其转储核心文件.程序被中止而没有生成core. 这与abort()例程的行为不同,该例程发送SIGABRT,因此,它使de kernel可以转储该进程的核心文件.

      When I say that the program is aborted by the kernel but in both cases, the signals involved (SIGINT and SIGALRM) don't make it to dump a core file. The program is aborted without generating core. This is different to the behaviour of the abort() routine, which sends a SIGABRT and so, it makes de kernel to dump a core file of the process.

      这篇关于在Linux中接收SIGINT和异常处理的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆