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

APUE所述早期UNIX信号特性与Ubuntu 22.04测试结果不符问题

问题解答

你遇到的情况是因为不同UNIX/Linux系统中signal()函数的实现行为存在历史差异:

  • 早期UNIX的signal()行为:正如APUE提到的早期版本(比如V7 UNIX),signal()注册信号处理函数后,当信号触发并执行处理函数时,系统会自动将该信号的处理动作重置为默认值(SIG_DFL)。所以当时必须在信号处理函数内部重新调用signal()来再次注册,否则下一次收到该信号时就会执行默认动作(比如终止进程)。

  • 现代Linux的signal()实现:Ubuntu 22.04使用的是glibc库,其中的signal()函数是POSIX兼容的改进实现,它底层通过sigaction()来实现,并且默认不会设置SA_RESETHAND标志(这个标志的作用就是触发信号后重置处理动作)。因此,每次收到信号时,处理函数会被重复调用,不会自动重置为默认行为。

如果你想模拟早期UNIX的signal()行为,可以直接使用sigaction()并显式设置SA_RESETHAND标志,示例代码如下:

#include <unistd.h>
#include <stdio.h>
#include <signal.h>

void sh(int signo) {
    printf("signo=%d\n", signo);
}

int main(int argc, char *argv[]) {
    struct sigaction act;
    act.sa_handler = sh;
    sigemptyset(&act.sa_mask);
    act.sa_flags = SA_RESETHAND; // 设置该标志,触发后重置处理动作

    sigaction(SIGUSR1, &act, NULL);

    while (1)
        pause();
    return 0;
}

编译运行这个代码后,第一次发送SIGUSR1会执行sh()函数,第二次发送该信号就会触发默认动作(终止进程),和早期UNIX的行为一致。

注意:信号处理函数中使用printf要谨慎,因为printf属于非可重入函数,在信号处理场景下可能出现未定义行为,生产环境中建议使用write()这类可重入函数来输出信息。

内容的提问来源于stack exchange,提问作者user14892865

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.14 06:04:53