嵌入式Linux:进程如何处理信号
2026-10-043
在 Linux 系统中,进程收到信号后,可以选择忽略信号、捕获信号并执行自定义处理函数,或执行系统默认操作。Linux 主要通过 signal() 和 sigaction() 设置信号处理方式。
signal() 函数
函数原型
#include <signal.h>
typedef void (*sig_t)(int);
sig_t signal(int signum, sig_t handler);
signum指定信号,可使用SIGINT等名称。handler是处理函数指针,也可以设置为SIG_IGN(忽略)或SIG_DFL(默认处理)。- 成功时返回之前的处理函数指针;失败返回
SIG_ERR并设置errno。
下面的示例捕获 SIGINT,打印信号编号后继续运行:
#include <stdio.h>
#include <signal.h>
#include <unistd.h>
static void handle_signal(int signal) {
printf("Caught signal %d\n", signal);
}
int main(void) {
signal(SIGINT, handle_signal);
while (1) {
printf("Running...\n");
sleep(1);
}
}
如果希望忽略 SIGINT,可以把注册语句改为 signal(SIGINT, SIG_IGN)。
sigaction() 函数
sigaction() 比 signal() 提供更细的控制和更好的可移植性,实际开发中通常优先使用它。
函数原型
#include <signal.h>
int sigaction(int signum, const struct sigaction *act,
struct sigaction *oldact);
signum 不能是 SIGKILL 或 SIGSTOP;act 描述新的处理方式,oldact 用于保存旧配置,不需要时可传 NULL。成功返回 0,失败返回 -1 并设置 errno。
结构体中的关键成员:
sa_handler:普通处理函数、SIG_IGN或SIG_DFL。sa_sigaction:带额外上下文的处理函数,需要配合SA_SIGINFO。sa_mask:处理函数执行期间临时阻塞的信号集合。sa_flags:控制行为,例如SA_RESTART、SA_NODEFER和SA_SIGINFO。
下面的示例使用 SA_SIGINFO 获取发送进程的 PID:
#include <stdio.h>
#include <signal.h>
#include <unistd.h>
static void handle_signal(int signal, siginfo_t *info, void *context) {
(void)context;
printf("Caught signal %d\n", signal);
printf("Signal sent by process %d\n", info->si_pid);
}
int main(void) {
struct sigaction act = {0};
act.sa_sigaction = handle_signal;
act.sa_flags = SA_SIGINFO;
sigemptyset(&act.sa_mask);
sigaction(SIGINT, &act, NULL);
while (1) {
printf("Running...\n");
sleep(1);
}
}
注意事项
进程没有显式设置处理方式时,通常使用系统默认动作。通过 fork() 创建子进程时,子进程会继承父进程的信号处理配置,但也可以在后续运行中重新设置。
信号处理函数应尽量短小,只执行设置标志、记录简单状态等必要操作。复杂逻辑放在主循环中处理,可以减少重入、竞争条件和全局状态不一致的风险。
来源:嵌入式Linux:进程如何处理信号(CSDN,原作者“不脱发的程序猿”,CC BY-SA 4.0)



