linux中捕获处理自定义信号应使用实时信号sigrtmin~sigrtmax,通过sigaction注册带sa_siginfo标志的处理函数,用sigqueue发送携带数据的信号,并遵守异步信号安全规则。

Linux 中捕获并处理自定义信号,核心是注册一个用户定义的处理函数,并确保该函数在信号递达时被安全、可靠地调用。注意:Linux 本身不支持真正“自定义编号”的信号(比如自己造个信号 123),但你可以使用系统预留的 实时信号(SIGRTMIN ~ SIGRTMAX,通常为 34~64) 来实现应用层意义上的“自定义信号”——它们可排队、可携带数据、行为确定,是推荐做法。
用 sigaction 注册实时信号处理函数
相比老旧的 signal(),sigaction() 是 POSIX 标准推荐方式,支持设置信号掩码、标志位和附加信息传递:
- 包含头文件:
#include <signal.h></signal.h> - 定义处理函数,支持带参数的增强模式(需设
SA_SIGINFO标志):void handler(int sig, siginfo_t *info, void *ucontext) {
printf("Received signal %d, value = %d\n", sig, info->si_value.sival_int);} - 初始化
struct sigaction:设置sa_sigaction(不是sa_handler),置SA_SIGINFO,用sigemptyset(&act.sa_mask)清空临时屏蔽集(或按需添加其他信号) - 调用
sigaction(SIGRTMIN + 1, &act, NULL)完成注册
发送实时信号并附带数据
仅注册不够,还需从另一端(同进程、父子进程或其它进程)发送带 payload 的信号:
Zynq‑7000 / Zynq UltraScale+ 硬件调试技能。适用于 Xilinx Zynq(Cortex‑A9/A53 + FPGA)Linux 环境,调试 I2C、I2S、UART、GPIO 等外设。包括设备树配置、内核驱动、用户空间调试工具、交叉编译和常见问题排查,支持 PetaLinux 开发。
- 使用
sigqueue(pid, sig, value)发送,其中value可为int或指针(需保证生命周期) - 例如:
union sigval val; val.sival_int = 42; sigqueue(getpid(), SIGRTMIN + 1, val); - 接收端在 handler 中通过
info->si_value获取该值,实现轻量级“带参通知”
避免常见陷阱
信号处理函数是异步进入的,环境受限,必须严格遵守可重入规则:
- 只调用异步信号安全函数(如
write()、sigprocmask()),禁用printf、malloc、pthread_create等 - 不要在 handler 中做耗时操作;适合做标记、写状态、触发后续主循环检查(如设置
volatile sig_atomic_t flag = 1) - 若需多信号协同,用
sa_mask在 handler 执行期间临时屏蔽同类或其他干扰信号 - 注意:SIGKILL(9)和 SIGSTOP(19)永远无法捕获或忽略,这是内核强制保障
Shell 脚本中用 trap 捕获常用信号
对脚本场景,无需 C 编程,直接用 trap 命令即可处理标准信号:
-
trap 'echo "Got SIGINT"; cleanup' INT—— Ctrl+C 时执行清理 -
trap 'exit 0' TERM HUP—— 收到 TERM 或 HUP 时静默退出 -
trap '' TSTP—— 忽略 Ctrl+Z(暂停) -
trap - INT—— 恢复默认行为(终止)










