You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何两次发送SIGINT信号(Ctrl-C)后信号处理器失效?

关于Linux下C语言信号处理器的疑问

我在Linux系统中学习编写C语言信号处理器,写了如下代码:

#include<stdio.h>
#include<signal.h>
#include<unistd.h>
void sig_handler(int signum){
    //Return type of the handler function should be void
    printf("\nInside handler function\n");
}

int main(){
    signal(SIGINT,sig_handler); // Register signal handler
    for(int i=1;;i++){    //Infinite loop
        printf("%d : Inside main function\n",i);
        sleep(1);  // Delay for 1 second
    }
    return 0;
}

疑问:为什么按下Ctrl+C两次后程序就停止了?按道理每次按下Ctrl+C都应该触发信号处理器,程序应该一直运行才对?

实际运行时,只有第一次Ctrl+C触发了信号处理器,第二次直接终止程序,输出如下:

1 : Inside main function
2 : Inside main function
3 : Inside main function
4 : Inside main function
^C
 Inside handler function
5 : Inside main function
6 : Inside main function
7 : Inside main function
8 : Inside main function
9 : Inside main function
10 : Inside main function
^C

原因分析

这是因为传统signal()函数的行为在不同系统实现中存在不一致性,在Linux的常见实现里,当信号被处理完成后,该信号的处理方式会被自动重置为默认行为(即SIG_DFL,直接终止进程)。

具体流程:

  • 第一次按下Ctrl+C触发SIGINT信号,自定义处理器sig_handler被执行,但执行结束后,SIGINT的处理逻辑被恢复为默认的终止操作。
  • 第二次按下Ctrl+C时,系统使用默认处理逻辑,直接终止了程序。

解决方法

方法1:使用标准可靠的sigaction()函数

sigaction()是POSIX标准定义的信号处理接口,行为稳定可预测,默认不会在信号处理后重置处理方式。修改后的代码如下:

#include<stdio.h>
#include<signal.h>
#include<unistd.h>

void sig_handler(int signum){
    printf("\nInside handler function\n");
}

int main(){
    struct sigaction sa;
    sa.sa_handler = sig_handler;
    sigemptyset(&sa.sa_mask);  // 处理信号时不阻塞其他信号
    sa.sa_flags = 0;           // 保持默认行为,不自动重置处理器
    
    sigaction(SIGINT, &sa, NULL);  // 注册信号处理器
    
    for(int i=1;;i++){
        printf("%d : Inside main function\n",i);
        sleep(1);
    }
    return 0;
}

方法2:在信号处理器内重新注册

如果坚持使用signal(),可以在自定义处理器函数末尾重新注册一次信号处理逻辑,确保下次信号到来时依然调用自定义处理器:

#include<stdio.h>
#include<signal.h>
#include<unistd.h>

void sig_handler(int signum){
    printf("\nInside handler function\n");
    signal(SIGINT, sig_handler);  // 重新注册信号处理器
}

int main(){
    signal(SIGINT, sig_handler);
    for(int i=1;;i++){
        printf("%d : Inside main function\n",i);
        sleep(1);
    }
    return 0;
}

两种方法都能实现每次按下Ctrl+C都触发自定义处理器,程序不会被终止。


内容的提问来源于stack exchange,提问作者JobHunter69

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.03 19:35:22