You need to enable JavaScript to run this app. Linux C语言下父进程正确获取子进程停止/继续/退出状态的方法
优惠活动
大模型
产品
解决方案
定价
更多

Linux C语言下父进程正确获取子进程停止/继续/退出状态的方法

问题根因与修正方案

一、语法错误修正

现有代码存在笔误,会直接导致编译失败:

  • 函数定义int waiting4pid()(pid_t processID)多了一对空括号,正确应为int waiting4pid(pid_t processID)
  • 所有调用处的waiting4pid()(processID)同样多了空括号,正确应为waiting4pid(processID)

二、异常原因分析

waitpid的返回值与传入的flags直接相关,原有waiting4pid的循环逻辑不符合获取子进程停止、继续、退出三类状态的需求:

  1. 不带WNOHANG时的阻塞原因
    原有while (waitpid(...) > 0)循环会在拿到一次状态后,立刻再次调用waitpid等待下一个状态事件。
    第一次发送SIGSTOP后,waitpid会立刻返回子进程的停止状态,处理完成后循环进入下一次waitpid调用,此时没有新的状态事件,waitpid就会阻塞,直到后续发送SIGCONT才返回继续状态,表现为“子进程恢复运行时waitpid阻塞”。
  2. 带WNOHANG时捕获不到停止状态的原因
    WNOHANG的作用是无状态事件时立刻返回0,不会等待。发送SIGSTOP后立刻调用waitpid(WNOHANG)时,子进程尚未完成停止状态切换,内核还未生成可获取的停止事件,waitpid直接返回0,while循环判断返回值不大于0直接退出,因此捕获不到停止状态。

三、阻塞模式正确实现

按照需求“每发送一个信号后,捕获对应状态即返回”的逻辑,修改waiting4pid函数,去掉多余的循环:

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

// 阻塞等待任意子进程状态事件,处理后立即返回
int waiting4pid(pid_t processID)
{   
    int currentState;
    pid_t waitRet = waitpid(processID, &currentState, WUNTRACED | WCONTINUED);
    if (waitRet == -1) {
        perror("waitpid error");
        return -1;
    }

    if(WIFCONTINUED(currentState)){
        printf("\n currentState = continued!\n");
    }
    if(WIFSIGNALED(currentState)){
        printf("\n currentState = signaled!\n");            
    }
    if(WIFSTOPPED(currentState)){
        printf("\n currentState = stopped!\n");
    }
    return 0;
}

void sigTest()
{ 
    pid_t processID;

    processID = fork();
    if(processID ==0) { // 子进程逻辑
       // tmp/loop 为25秒计数的测试程序
       execlp("tmp/loop", "tmp/loop", NULL);
       // exec失败时直接退出,避免执行父进程逻辑
       perror("execlp error");
       _exit(1);
    }else{ // 父进程逻辑
        sleep(2);
        printf("\n Stop!");
        kill(processID, SIGSTOP);
        waiting4pid(processID);
        
        sleep(2);
        printf("\n Continue!");      
        kill(processID,SIGCONT);
        waiting4pid(processID);
        
        sleep(2);
        printf("\n Kill!"); 
        kill(processID, SIGKILL);
        waiting4pid(processID);
    }
}

int main() 
{    
    sigTest();
    return 0;
}

四、非阻塞模式(带WNOHANG)实现

若父进程需要在等待子进程状态的同时处理其他逻辑,可修改为轮询模式,持续检查直到拿到目标状态:

int waiting4pid(pid_t processID)
{   
    int currentState;
    while (1) {
        pid_t waitRet = waitpid(processID, &currentState, WUNTRACED | WCONTINUED | WNOHANG);
        if (waitRet == -1) {
            perror("waitpid error");
            return -1;
        }
        if (waitRet == 0) {
            // 暂时无状态事件,可在此插入其他处理逻辑,休眠避免CPU空转
            usleep(10000);
            continue;
        }
        // 拿到状态事件,处理后返回
        if(WIFCONTINUED(currentState)){
            printf("\n currentState = continued!\n");
        }
        if(WIFSIGNALED(currentState)){
            printf("\n currentState = signaled!\n");            
        }
        if(WIFSTOPPED(currentState)){
            printf("\n currentState = stopped!\n");
        }
        return 0;
    }
}

注意:轮询模式下每次无事件时增加10ms休眠,避免CPU被空转占满。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.25 12:54:03