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

为何孤儿进程组会出现信号不一致的情况?

为何孤儿进程组会出现信号不一致的情况?

最近我在啃《UNIX环境高级编程》里的孤儿进程组例子,写了段测试代码,结果发现个奇怪的事儿:同一个进程组里的进程,有的收到了SIGHUP信号打出了日志,有的却啥反应都没有,看起来信号处理完全不一致。先给你看看我写的测试代码:

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

static void sig_hup(int signo) {
    printf("SIGHUP received, pid = %ld\n", (long)getpid());
}

static void pr_ids(char *name) {
    printf("%s: pid = %ld, ppid = %ld, pgrp = %ld, tpgrp = %ld\n",
            name, (long)getpid(), (long)getppid(), (long)getpgrp(),
            (long)tcgetpgrp(STDIN_FILENO));
    fflush(stdout);
}

int main(void) {
    char c;
    pid_t pid;

    pr_ids("parent");
    if ((pid = fork()) < 0) {
        perror("fork error");
    } else if (pid == 0) { /* 子进程逻辑 */
        pr_ids("child");
        signal(SIGHUP, sig_hup); /* 自定义SIGHUP信号处理函数 */
        kill(getpid(), SIGTSTP); /* 让自己停止运行 */
        pr_ids("child");
        if (read(STDIN_FILENO, &c, 1) != 1)
            printf("read error from control terminal, errno = %d\n", errno);
        exit(0);
    } else { /* 父进程逻辑 */
        sleep(5); /* 等待子进程进入停止状态 */
        exit(0); /* 父进程退出,子进程所在组变成孤儿进程组 */
    }
    exit(0);
}

跑这段代码的时候,我发现子进程打出了SIGHUP received的日志,但如果我再加个保持运行状态的子进程,那个进程就没任何输出——当时我就挠头了:都是同一个孤儿进程组的,咋信号待遇差这么多?

后来翻了资料才搞懂这儿的门道,给你唠唠:

  • 首先得明确啥是孤儿进程组:当进程组里所有进程的父进程,都不在当前会话里了,这个进程组就成了没人管的“孤儿”。
  • UNIX系统对孤儿进程组有个保护机制:如果孤儿进程组里有进程正处于停止状态(比如收到SIGTSTP、SIGSTOP这类信号挂起了),系统会给这个进程组里的所有进程发SIGHUP信号,紧接着再发SIGCONT信号——目的是让这些挂起的进程别一直躺平没人管,要么被终止要么继续运行。
  • 那为啥看起来“信号不一致”?核心原因有两个:
    • 一是进程状态不同:如果进程是运行状态,收到SIGHUP信号后,默认处理是直接终止进程;要是你没自定义处理函数,进程直接就没了,自然看不到输出;而停止状态的进程收到SIGHUP+SIGCONT后,会被唤醒,执行你自定义的信号处理函数,所以能看到日志。
    • 二是信号处理方式不同:要是有的进程你设了忽略SIGHUP,有的设了捕获,有的用默认处理,那表现肯定不一样。比如我代码里的子进程捕获了SIGHUP,所以能打印日志;要是另一个子进程没设处理函数,收到SIGHUP直接就挂了,你根本看不到它的输出,就会误以为它没收到信号。

举个直白的例子:我代码里的子进程先自己挂起,父进程退出后它所在的组变成孤儿进程组,触发了SIGHUP+SIGCONT,所以子进程被唤醒,执行sig_hup函数打出日志;但如果我让另一个子进程一直循环运行,父进程退出后,这个运行中的子进程收到SIGHUP直接就被终止了,连打印的机会都没有,看起来就像是“没收到信号”,实际上是收到了但直接挂了。

说白了,不是信号发的不一致,是不同状态、不同处理方式的进程,收到信号后的表现不一样,才让你产生了“信号不一致”的错觉。

内容来源于stack exchange

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.08 12:49:30