繁体   English   中英

为什么 C 中的 signal() function 只能工作一次

[英]why signal() function in C only works once

这是我的代码:

#include<stdio.h>
#include<stdlib.h>
#include<signal.h>
#include<setjmp.h>

void sighandler(int signum);
jmp_buf buf;
void main(){
    signal(SIGINT,sighandler);

    if(!setjmp(buf))
        printf("welcome to this game\n");
    
    int a = 1;
    printf("raw value of a is %d\n",a);
    printf("modify a:");
    scanf("%d",&a);
    printf("new value of a is %d\n",a);
}
void sighandler(int signum){
    if(signum == SIGINT){
        printf("\nyou can't quit this game by ctrl+C,now we will restart it\n");
        longjmp(buf,1);
    }
}

我在 ubuntu 上运行它,结果如下:

welcome to this game
raw value of a is 1
input num to modify a:^C
you can't quit this game by ctrl+C,now we will restrat it
raw value of a is 1
input num to modify a:^C

似乎 signal() 仅第一次捕获 SIGINT。 我在网站上阅读了一些答案,例如:

“当一个信号被传递时,它在处理程序的执行过程中也会被阻塞(如果从 SIGINT 传递中调用它,则在 sigint_handler 中执行时不会传递任何 SIGINT);”

但我不明白,因为我的 signal_handler function 应该很快退出。 我不知道为什么被阻止。有没有办法让它第二次或第三次工作? 谢谢

在您的信号处理程序中,SIGINT 被阻止,也就是说,它被添加到您的进程的信号掩码中。 (1)

当您使用longjmp (非本地 goto)离开信号处理程序时,信号掩码不会被触及。 因此,当您在setjmp点恢复执行时,您会保留处理程序设置的信号掩码。 (2)

sigsetjmpsiglongjmp通过保存和恢复信号掩码解决了这个问题。

但是,我建议您重新编写代码以完全避免非本地 goto。 它们可以安全使用,但容易误用且难以推理。

笔记:

  1. signal的这种行为很常见,但并不普遍,这是更喜欢sigaction signal而不是 signal 的一个很好的理由。
  2. 如果您从处理程序正常返回,系统将为您重置掩码。

您实际上并没有从信号处理程序返回(当然,您退出它,但您没有从它返回 - 您只是跳转到另一个上下文)。 如果您让信号处理程序返回,您的代码将在它停止的地方继续执行,并且它会按照您想要的方式拦截任何后续的 SIGINT 信号。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM