为何设置SA_SIGINFO的SIGQUIT信号无法实现可靠排队?
问题分析:为何SA_SIGINFO没让SIGQUIT实现信号排队?
你这里的问题其实是混淆了SA_SIGINFO的作用和可靠信号(实时信号)的特性,咱们一步步理清楚:
首先明确一个核心知识点:SA_SIGINFO 不是让普通信号变成可排队的可靠信号的开关。它的主要作用是让信号处理函数能获取额外的信号元数据(比如发送进程的PID、信号携带的附加数据等),而信号是否支持排队,完全取决于信号本身的类型——只有**实时信号(SIGRTMIN 到 SIGRTMAX,通常是34到63)**才支持可靠排队,传统的普通信号(1-31,比如SIGQUIT、SIGINT这些)不管有没有SA_SIGINFO,都是不可靠的,重复发送的信号会被合并,只会保留一个实例。
你的代码与预期不符的原因
你注册了SIGQUIT的处理函数并设置了SA_SIGINFO,但SIGQUIT属于普通信号范畴,所以即使你多次发送,阻塞期间pending队列里只会保留一个信号实例,解除阻塞后也只会触发一次处理函数,这就是你看到输出只有一个signo = 3的原因。
APUE里提到的“设置SA_SIGINFO实现可靠排队”,其实是指实时信号配合SA_SIGINFO使用时,不仅能实现信号排队,还能在处理函数里拿到每个信号的详细信息(比如区分不同发送的信号、获取携带的数据)——SA_SIGINFO是给可靠信号的排队功能“锦上添花”,而非让普通信号“脱胎换骨”。
验证可靠信号排队的修改示例
如果你想测试可靠信号的排队特性,可以把代码里的SIGQUIT换成实时信号(比如SIGRTMIN),修改后的代码如下:
#include <stdio.h> #include <signal.h> #include <unistd.h> void handler (int signo, siginfo_t * info, void *) { printf("signo = %d\n", signo); } int main() { struct sigaction act; act.sa_flags = 0; act.sa_flags |= SA_RESTART; act.sa_flags |= SA_SIGINFO; act.sa_sigaction = handler; // 改用实时信号SIGRTMIN sigaction(SIGRTMIN, &act, NULL); // 阻塞实时信号 sigset_t newmask; sigaddset(&newmask, SIGRTMIN); sigprocmask(SIG_BLOCK, &newmask, NULL); printf("send SIGRTMIN signals many times to me\n"); sleep(20); // 检查pending状态 sigset_t pending_set; sigpending(&pending_set); if(sigismember(&pending_set, SIGRTMIN)) { printf("pending\n"); } else { printf("not pending\n"); } // 解除阻塞 sigprocmask(SIG_UNBLOCK, &newmask, NULL); while(1); }
编译运行后,多次发送实时信号:
[markity@mycom ~]$ kill -SIGRTMIN 3676 [markity@mycom ~]$ kill -SIGRTMIN 3676 [markity@mycom ~]$ kill -SIGRTMIN 3676 [markity@mycom ~]$ kill -SIGRTMIN 3676 [markity@mycom ~]$ kill -SIGRTMIN 3676 [markity@mycom ~]$ kill -SIGRTMIN 3676 [markity@mycom ~]$ kill -SIGRTMIN 3676
此时程序的输出就会符合你的预期:
[markity@mycom theory]$ ./main send SIGRTMIN signals many times to me pending signo = 34 signo = 34 signo = 34 signo = 34 signo = 34 signo = 34 signo = 34
总结
- 普通信号(1-31):不可靠,重复发送会被合并,仅保留一个实例,和SA_SIGINFO无关。
- 实时信号(34+):可靠,支持排队,配合SA_SIGINFO可以在处理函数中获取每个信号的详细信息。
- SA_SIGINFO的核心价值是提供信号的元数据访问能力,而非让普通信号变可靠。
内容的提问来源于stack exchange,提问作者Markity
相关产品推荐
相关产品推荐

