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

调用getpgid(child_pid)获父进程ID/GID而非子进程GID的问题排查

问题

我想从父进程中获取子进程的组ID(PGID)并存储到job结构体里,但调用getpgid(child_pid)时得到的却是父进程的PID/PGID,除了组ID获取外其他功能都正常。我怀疑自己对PID和PGID的理解有问题,但找不到问题所在。

我的代码:

if ((newJob->pid = Fork()) == 0)
{
    
    if (setpgid(0, 0) == -1)
    {
        perror("setpgid() error");
    }
    printf("fork pid: %d\n", getpid());
    printf("fork gid: %d\n", getpgrp());
    execve(command, customArgv, NULL);
}

printf("parent pid: %d\n", getpid());
printf("parent gid: %d\n", getpgrp());
printf("fork pid from parent: %d\n", newJob->pid);
printf("fork gid from parent: %d\n", getpgid(newJob->pid));

输出:

parent pid: 2631063
parent gid: 2631063
fork pid from parent: 2631093
fork gid from parent: 2631063
fork pid: 2631093
fork gid: 2631093
分析与解决

问题核心是父子进程的执行顺序不同步:父进程调用getpgid(newJob->pid)时,子进程可能还没来得及执行setpgid(0, 0)修改自身进程组ID。此时子进程仍属于父进程的进程组,所以getpgid返回的是父进程的PGID。

有两种可靠的解决方式:

方式1:父进程轮询等待子进程完成PGID设置

让父进程循环检查子进程的PGID,直到其不再等于父进程的PGID(说明子进程已完成setpgid操作):

if ((newJob->pid = Fork()) == 0)
{
    if (setpgid(0, 0) == -1)
    {
        perror("setpgid() error");
    }
    printf("fork pid: %d\n", getpid());
    printf("fork gid: %d\n", getpgrp());
    execve(command, customArgv, NULL);
}

// 父进程轮询等待子进程设置好PGID
int target_pgid;
do {
    target_pgid = getpgid(newJob->pid);
    usleep(1000); // 短暂休眠避免CPU占用过高
} while (target_pgid == getpgrp());

printf("parent pid: %d\n", getpid());
printf("parent gid: %d\n", getpgrp());
printf("fork pid from parent: %d\n", newJob->pid);
printf("fork gid from parent: %d\n", target_pgid);

方式2:父进程主动为子进程设置PGID

直接在父进程中调用setpgid为子进程设置进程组,无需子进程自行操作,这种方式更可控:

if ((newJob->pid = Fork()) == 0)
{
    printf("fork pid: %d\n", getpid());
    printf("fork gid: %d\n", getpgrp());
    execve(command, customArgv, NULL);
}

// 父进程为子进程设置进程组ID
if (setpgid(newJob->pid, newJob->pid) == -1)
{
    perror("parent setpgid() error");
}
int target_pgid = getpgid(newJob->pid);

printf("parent pid: %d\n", getpid());
printf("parent gid: %d\n", getpgrp());
printf("fork pid from parent: %d\n", newJob->pid);
printf("fork gid from parent: %d\n", target_pgid);

补充说明

  • setpgid(0,0)的作用是将当前进程(子进程)设为新进程组的组长,进程组ID等于子进程自身的PID。
  • 进程创建后默认继承父进程的进程组ID,直到通过setpgid主动修改。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.12 07:05:31