当前位置: 首页 > 面试题库 >

在Linux中接收SIGINT和异常处理

崔绍辉
2023-03-14
问题内容

假设我们在C中有一个使用sleep()函数的程序

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

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

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

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)
}

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

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

问题1:我的理解是,内核通过更新在插入位向量中SIGINT的对应挂起位将SIGINT发送到进程,我的理解正确吗?

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

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


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

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

  • 问题3: 好吧,您的推论是基于错误的前提,也就是说, 中断待处理标志表明已接收到中断 。该位 预示着未处理中断已被标记为交付 只要你解锁 ,而这只有在其他系统调用发生(解除阻塞信号)。一旦信号被解除阻塞,sigsetmask(2)系统调用的返回代码将执行信号处理程序。在这种情况下,信号将在计时器经过后立即传递到进程,系统调用将被中断,并且,如果您尚未为信号安装信号处理程序 SIGALRM(但sleep(2)实现则至少在以前这样做)实施)程序将被中止。

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



 类似资料:
  • 问题内容: 我正在使用SpringMVC在带有Spring的应用程序上工作,遇到以下错误,我不知道如何处理。 现在我在控制台中收到此消息: 这是我的ImportController类 这是我的Employe.hbm.xml 这是我的Departement.hbm.xml 调试后,问题出在这里: 恰好在这里: 这个DepartementImplDB类 可以提供帮助吗? 问题答案: 你的错误是 在您的

  • 问题内容: 我有一个使用Qt Framework的简单程序。它使用QProcess执行RAR并压缩一些文件。在我的程序中,我正在捕获并在发生代码时做一些事情: 当发生时,我检查RAR进程是否完成,如果不是,我将等待它……问题是(我认为)RAR进程也得到了我的程序所需要的,并且在压缩之前退出了所有的文件。 有没有一种方法可以运行RAR进程,以便在程序接收到它时不接收它? 谢谢 问题答案: 如果要在U

  • 80386实地址模式下的中断和异常处理与8086是一样的。中断和异常通过中断表指向处理函数。处理器将中断和异常标识符乘以4来获得其在中断表的索引。中断表是指向处理函数的长指针。当中断发生时,处理器将CS:IP压栈,关中断,清TF(单步标志位),然后将控制权交给中断表指向的函数。在处理函数末尾的IRET执行相反的过程,并将控制权交还给被中断的进程。 80386的中断处理与8086的最大不同之处在于中

  • 我正在做我的一项任务。这相当直截了当。包含单个输入的HTML表单被提交到Servlet,Servlet获取参数,基于参数创建消息,将消息作为属性添加到请求,并使用requestdispatcher转发到jsp以显示消息。 我有一个要求,如果参数丢失,我需要显示一个错误页面。问题是我不能显式地检查null,也不能使用try/catch块。我的猜测是,目标是在web中定义错误页面。xml页面来处理特定

  • 本文向大家介绍.NET中的异常和异常处理用法分析,包括了.NET中的异常和异常处理用法分析的使用技巧和注意事项,需要的朋友参考一下 本文较为详细的分析了.NET中的异常和异常处理用法。分享给大家供大家参考。具体分析如下: .NET中的异常(Exception) .net中的中异常的父类是Exception,大多数异常一般继承自Exception。 可以通过编写一个继承自Exception的类的方式

  • 问题内容: 异常处理中的块究竟执行什么功能? 问题答案: 它包含应始终执行的代码,无论是否发生异常。 例如,如果您打开了一个文件,则应在块中将其关闭,以确保始终关闭该文件。如果在块中将其关闭,则较早的异常将导致执行直接跳到该块并跳过关闭文件。 有关更多详细信息,请参见Java教程。