直接查看/proc/[pid]/status中的SigPnd、SigBlk、SigCgt三行是唯一能同时准确区分挂起、屏蔽、已注册handler状态的权威方法;ps等命令仅反映部分静态注册信息,无法体现动态阻塞与递达情况。

直接看 /proc/[pid]/status 里的 SigPnd、SigBlk、SigCgt 三行,是唯一能同时区分「挂起」「屏蔽」「已注册 handler」的权威来源。其他命令如 ps 只反映部分状态,容易误判。
怎么查进程当前信号的 pending / blocked / caught 状态
内核通过三个 64 位十六进制位图字段暴露信号状态,必须手动解析位图才能准确判断:
-
SigPnd:挂起信号(已发送但未递达),比如发了SIGUSR1但进程正屏蔽它,就会卡在这里 -
SigBlk:当前被sigprocmask()屏蔽的信号掩码,对应阻塞状态 -
SigCgt:已用signal()或sigaction()注册过 handler 的信号集合
低位(bit 0)对应信号 1(SIGHUP),高位(bit 31)对应信号 32(RTMAX),普通信号只占低 32 位。例如 SigCgt: 0000000000000240 转十进制是 576,二进制为 1001000000,从右往左数第 10 位(bit 9)为 1 → 对应信号 10(SIGUSR1)已注册 handler。
Linux 性能分析与调优专家,覆盖 CPU、内存、磁盘 I/O、网络、内核参数、编译优化、容器/K8s。适用场景:系统卡顿/高负载、内存不足/OOM/Swap 高、CPU 异常/iowait 高。
为什么 ps -o sigcatch,sigign 不够用
ps 输出的 sigcatch 和 sigign 只告诉你「注册了 handler」或「显式忽略」,但完全不体现信号是否被屏蔽(SigBlk)或是否挂起(SigPnd):
- 某信号在
sigcatch里 → 说明有 handler,但若SigBlk中该位也为 1,则信号根本不会递达,handler 永远不触发 - 某信号不在
sigcatch也不在sigign→ 默认行为(如SIGTERM终止),但如果被屏蔽,照样不会生效 -
ps的sig字段是阻塞掩码,但用的是十进制位图,和/proc/[pid]/status的十六进制格式不一致,易算错
strace -e signal 是唯一验证「信号真被收到」的方法
即使 SigCgt 显示已注册 handler,SigBlk 显示未屏蔽,也得靠 strace 确认内核是否真把信号递送到了用户态:
- 运行
strace -p [pid] -e trace=signal,然后发信号(如kill -USR1 [pid]) - 若看到类似
--- SIGUSR1 {si_signo=SIGUSR1, si_code=SI_USER, ...} ---,说明递达成功 - 全程无输出?不是没发,就是被屏蔽(
SigBlk中该位为 1)、发错 PID、或权限不足(非 root 向其他用户进程发信号会被拒绝) - 注意:
strace本身会劫持信号路径,某些信号(如SIGSTOP)可能被它截获,仅限调试,不能长期挂载
信号状态是动态的,SigPnd 和 SigBlk 可能在毫秒级变化;解析位图时别漏掉前导零,64 位全宽必须对齐,否则位序全错。

















