You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何设置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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.04 18:15:36