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

如何用C语言实现响应SIGTERM生成子进程的可靠守护进程?

解决SIGTERM触发后子进程退出或无法接收信号的问题

先给你修正后的可运行代码,能实现你要的功能:收到SIGTERM就fork子进程,父进程退出,子进程继续监听信号,循环往复:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <sys/types.h>

static void handler(int signum)
{
    if (signum == SIGTERM)
    {
        pid_t pid = fork();
        if (pid < 0)
        {
            perror("Fork failed");
            exit(EXIT_FAILURE);
        }
        if (pid > 0)
        {
            // 父进程直接退出
            exit(EXIT_SUCCESS);
        }
        // 子进程重新配置信号处理(确保可靠)
        struct sigaction sa;
        sa.sa_handler = handler;
        sigemptyset(&sa.sa_mask);
        sa.sa_flags = SA_RESTART; // 让被信号中断的系统调用自动重启
        if (sigaction(SIGTERM, &sa, NULL) == -1)
        {
            perror("sigaction failed");
            exit(EXIT_FAILURE);
        }
        printf("Child process created (PID: %d)\n", getpid());
    }
}

int main(void)
{
    // 第一次fork创建守护进程,脱离父进程
    pid_t pid = fork();
    if (pid < 0)
    {
        perror("Fork failed");
        exit(EXIT_FAILURE);
    }
    if (pid > 0)
    {
        exit(EXIT_SUCCESS);
    }

    // 配置SIGTERM的可靠信号处理
    struct sigaction sa;
    sa.sa_handler = handler;
    sigemptyset(&sa.sa_mask);
    sa.sa_flags = SA_RESTART;
    if (sigaction(SIGTERM, &sa, NULL) == -1)
    {
        perror("sigaction failed");
        exit(EXIT_FAILURE);
    }

    printf("Daemon started (PID: %d)\n", getpid());

    // 主循环保持进程存活
    while (1)
    {
        sleep(1);
    }

    return EXIT_SUCCESS;
}

为啥你原来的代码有问题?

  1. 第一个版本子进程退出:
    你用的signal()函数是老式实现,信号触发一次后,系统会自动把信号处理重置为默认动作(SIGTERM默认是终止进程)。子进程从处理函数返回后,虽然回到主循环,但此时SIGTERM的处理已经变回默认,再发信号直接就会被终止。另外sleep()被信号中断后会提前返回,但主循环本来能继续,只是信号处理没了导致后续无法响应。

  2. 第二个版本子进程收不到信号:
    你在信号处理函数里加了无限循环,进程会一直卡在处理函数里,根本回不到主循环。而且信号处理期间,同类型信号会被阻塞,就算重新注册也没用——进程都没机会处理新信号。

关键修复点

  • 用sigaction()代替signal():这是POSIX标准的可靠信号处理,不会自动重置处理函数,还能通过参数控制行为。
  • 加SA_RESTART标志:让sleep()这种被信号中断的系统调用自动重启,避免主循环因为sleep()返回错误而意外退出。
  • 信号处理函数别搞复杂:只做fork和必要配置,然后返回,让进程回到主循环继续监听,别在处理函数里写循环。

内容的提问来源于stack exchange,提问作者Íñigo Aldaraborda

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.08 05:33:22