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

Linux下C程序信号处理疑问:捕获所有信号及发送方式

Linux信号捕获与发送问题解答

一、关于“所有可能的信号”的定义

kill -l命令列出的是当前Linux系统支持的全部信号,通常包含两类:

  • 标准信号(1-31):POSIX定义的基础信号,比如SIGINT(2)、SIGTERM(15)等;
  • 实时信号(34-64):用于应用程序间实时通信,编号可能因系统略有差异。

但不是所有信号都能被捕获:其中SIGKILL(9)和SIGSTOP(19)是内核强制处理的信号,无法被用户程序捕获、忽略或修改处理逻辑,编写捕获程序时可直接跳过这两个信号。

换句话说,你需要处理的是kill -l列出的信号中,除9和19之外的所有信号,而非全部64种。

二、无键盘快捷键的信号发送方式

除了Ctrl-C(SIGINT)、Ctrl-Z(SIGTSTP)、Ctrl-\(SIGQUIT)这些键盘触发的信号,其他信号可通过以下方式发送:

  • kill命令:指定进程PID和信号编号/名称发送,比如给PID为1234的进程发SIGUSR1信号:
    kill -USR1 1234
    # 或用信号编号(SIGUSR1通常是10)
    kill -10 1234
    
  • pkill/killall命令:按进程名匹配发送信号,比如给所有名为signal_catch的进程发SIGHUP信号:
    pkill -HUP signal_catch
    # 或用killall
    killall -HUP signal_catch
    
  • C程序内部发送:
    • 用kill()系统调用给指定PID发信号,比如给自己发SIGUSR2:
      #include <signal.h>
      #include <unistd.h>
      kill(getpid(), SIGUSR2);
      
    • 用raise()函数给自己发信号,比如触发SIGALRM:
      raise(SIGALRM);
      

三、简单的信号捕获示例程序

以下是遍历可捕获信号、设置处理函数并打印信号ID的C程序:

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

void signal_handler(int sig) {
    printf("捕获到信号:%d\n", sig);
}

int main() {
    // 遍历1-64号信号,跳过无法捕获的SIGKILL(9)和SIGSTOP(19)
    for (int sig = 1; sig <= 64; sig++) {
        if (sig == 9 || sig == 19) {
            continue;
        }
        // 尝试注册信号处理函数
        if (signal(sig, signal_handler) == SIG_ERR) {
            fprintf(stderr, "无法注册信号 %d 的处理函数\n", sig);
        }
    }

    printf("程序已启动,等待信号输入...\n");
    while (1) {
        pause(); // 挂起进程,直到收到信号
    }

    return 0;
}

编译运行命令:

gcc signal_catch.c -o signal_catch
./signal_catch

打开另一个终端测试,比如:

# 查看进程PID
ps aux | grep signal_catch
# 发送SIGUSR1信号
kill -USR1 <进程PID>

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.11 18:45:31