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

如何让父进程停止等待且不退出当前进程?

让子进程不退出时通知父进程结束等待的实现方法

要实现子进程不退出就通知父进程停止阻塞等待,核心是通过信号或进程间通信(IPC)机制打破父进程的等待逻辑。下面给出两种常用的实现方案:

方法一:使用自定义信号(最简单直接)

利用Linux的自定义信号(比如SIGUSR1),子进程发送信号唤醒父进程,父进程收到信号后退出等待逻辑,同时保留运行状态。

修改后的完整代码:

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

// 信号处理函数,空实现即可,仅用于触发唤醒
void sig_handler(int sig) {}

int main() {
    // 注册SIGUSR1信号的处理函数
    signal(SIGUSR1, sig_handler);

    pid_t p1 = fork();
    if (p1) {
        printf("parent: %d\n", getpid());
        int stat;
        pid_t wait_ret;

        while (1) {
            // 非阻塞检查子进程是否意外退出
            wait_ret = waitpid(p1, &stat, WNOHANG);
            if (wait_ret == p1) {
                printf("child exited unexpectedly\n");
                break;
            } else if (wait_ret == -1) {
                perror("waitpid error");
                break;
            }
            // 阻塞等待信号到来
            pause();
            // 收到信号后停止等待,继续执行
            printf("parent received signal, stop waiting\n");
            break;
        }

        printf("parent continues running...\n");
        // 后续可以继续监控子进程或执行其他逻辑
        waitpid(p1, &stat, 0);
        printf("parent end\n");
    } else {
        printf("child: %d\n", getpid());
        printf("child parent: %d\n", getppid());
        sleep(3);
        // 发送SIGUSR1信号给父进程,通知停止等待
        kill(getppid(), SIGUSR1);
        sleep(3);
        printf("child end\n");
    }
    return 0;
}

关键逻辑说明

  • 父进程提前注册SIGUSR1信号的处理函数(空函数即可,只需要触发唤醒)
  • 父进程用waitpid(WNOHANG)非阻塞检查子进程状态,避免子进程意外退出时父进程永久阻塞
  • 子进程在需要通知的位置调用kill(getppid(), SIGUSR1),向父进程发送信号,唤醒父进程的pause()阻塞

方法二:使用匿名管道(更可靠的IPC方式)

通过匿名管道实现进程间同步,父进程阻塞在管道读端,子进程写入数据后父进程立即停止等待,这种方式不会出现信号丢失的问题,可靠性更高。

修改后的完整代码:

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

int main() {
    int pipe_fd[2];
    // 创建匿名管道
    if (pipe(pipe_fd) == -1) {
        perror("pipe error");
        exit(EXIT_FAILURE);
    }

    pid_t p1 = fork();
    if (p1) {
        printf("parent: %d\n", getpid());
        // 父进程关闭管道写端
        close(pipe_fd[1]);
        char buf;
        // 阻塞读取管道,收到数据后停止等待
        read(pipe_fd[0], &buf, 1);
        printf("parent received notification, stop waiting\n");
        close(pipe_fd[0]);

        // 继续监控子进程状态
        int stat;
        waitpid(p1, &stat, 0);
        printf("parent end\n");
    } else {
        printf("child: %d\n", getpid());
        printf("child parent: %d\n", getppid());
        // 子进程关闭管道读端
        close(pipe_fd[0]);
        sleep(3);
        // 向管道写入一个字节,通知父进程
        write(pipe_fd[1], "x", 1);
        close(pipe_fd[1]);
        sleep(3);
        printf("child end\n");
    }
    return 0;
}

关键逻辑说明

  • 父进程在fork前创建管道,确保父子进程共享管道文件描述符
  • 父进程关闭写端,阻塞在read()调用上;子进程关闭读端,在需要通知时写入一个字节
  • 父进程读到数据后立即退出等待,后续可以继续执行其他逻辑或监控子进程

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.22 04:37:44