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 1234pkill/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
相关产品推荐
相关产品推荐

