如果父进程仍在运行,子进程的 PID 是不是可供重用?

Posted

技术标签:

【中文标题】如果父进程仍在运行,子进程的 PID 是不是可供重用?【英文标题】:Does the PID of a child process become available for reuse if the parent process is still running?如果父进程仍在运行,子进程的 PID 是否可供重用? 【发布时间】:2015-12-11 19:11:02 【问题描述】:

我在基于 *nix 的操作系统上运行,并且有一个脚本可以同时启动多个进程。我的主要目标是同时启动这些进程,并为每个进程收集返回的退出状态。我发现使用wait(pid) 可以实现这一点,因为所有子进程都归父进程所有。但是,我担心一旦子进程(启动的并发进程之一)完成,它的 PID 将被释放并可以在系统内回收。

所以我想问题是,如果一个父进程同时启动多个子进程,是否会在父进程完成之前将完成的子进程的 PID 提供给系统用于回收之前 ?如果是这样,我怎样才能最好地获取每个子进程的退出状态?

下面的 bash 脚本示例:

local file=$1
local count=0
<files are split; and suffixed with aa,ab,ac,ad>

/home/text/concurrencyTest.sh $file-aa >> /home/text/$file-aa.log 2>&1 &
/home/text/concurrencyTest1.sh $file-ab >> /home/text/$file-ab.log 2>&1 &
/home/text/concurrencyTest2.sh $file-ac >> /home/text/$file-ac.log 2>&1 &
/home/text/concurrencyTest3.sh $file-ad >> /home/text/$file-ad.log 2>&1 &

for job in `jobs -p`
do
    echo "Job: $job"
    wait "$job"
    rc=$?
    echo "RC for $job is $rc"
    if [[ rc -ne 0 ]]; then
        FAIL[$count]="$job"
        ((count++))
    fi
done
if [[ $count -ne 0 ]]; then
    echo "ERROR: $count Job(s) Failed!"
    echo "Failed Process PID(s): $FAIL[@]"
    echo "Failed Processing for file: $file"
    return 1
fi

【问题讨论】:

【参考方案1】:

当父进程调用 waitwaitpid(或该家族的任何其他函数,例如 wait3wait4 等)时,子进程的 PID 变得可供重用。

当孩子死后,它作为僵尸留在后面——进程表中的一个条目,后面没有进程,它留在后面只是为了保留进程 ID 并存储退出状态。调用waitpid 会阻塞直到指定的子进程死亡(或者如果它已经死亡,则立即返回),检索子进程的状态代码,并收获僵尸(即删除进程表条目,释放进程 ID 以供重用)。调用wait 是类似的,但只要一个子进程死亡就会返回。

如果父进程在进程死亡时忽略了SIGCHLD 信号,则该进程不会变成僵尸进程,它的 PID 会立即可供重用。父母相对于 SIGCHLD 的状态在其他方面很重要;参见例如POSIX 了解详细信息。

如果父进程在子进程之前死亡,则称子进程是 init 收养的孤儿,该进程的 PID 为 1。获取孤儿是 init 工作的一部分。

在 shell 脚本中,wait 内置函数是 wait 系统调用的包装器。如果脚本有多个子进程,wait 没有参数会阻塞,直到所有子进程都死掉,wait 有一些参数会阻塞,直到所有指定的进程都死掉(没有办法等到一个进程死掉而不指定哪个进程) )。如果wait $pid1 返回,则可能$pid2 已经死亡并已被另一个进程重用;然而,即使如此,shell 仍会跟踪$pid2 的状态码,随后的wait $pid2 将返回其状态码。不过,在此之前,您不应派生新的后台作业,以免在 $pid2 被重用于后台作业时造成混淆。

【讨论】:

太棒了!感谢您的答复。我的理解是,即使其中一个子进程 PID 可能已被回收并用于系统内的其他内容(因为它以某种状态退出),随后的等待 $pid2 仍将为子进程返回正确的退出状态处理我关心的PID。这是因为 shell 在退出时维护子进程的状态,即使 PID 可能已被回收。再次感谢! 如果 $pid2 的 PID 已被回收并用于父级外部启动的单独后台进程,后续等待 $pid2 是否仍会返回正确的状态码过程? @mjshort 如果$pid2 已被该shell 的后台作业以外的任何东西回收,则shell 甚至不会知道它,它只会返回它存储的值。只有在两个未等待的后台作业最终具有相同的 PID 的情况下才会出现问题,并且只有在第一个作业死亡并且脚本执行了 wait 后第二个作业被分叉时才会发生这种情况内置用于不同的 PID。

以上是关于如果父进程仍在运行,子进程的 PID 是不是可供重用?的主要内容,如果未能解决你的问题,请参考以下文章

有没有办法检查子进程是不是仍在运行?

python多进程

进程管理

进程与进程间通信

使用共享内存的 IPC

僵尸进程