调用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
相关产品推荐
相关产品推荐

