Bash:为什么kill -STOP一个子进程使我的子进程和当前进程在ps中显示相同的命令行

问题描述

我在脚本中有这段代码。这是一个名为test.sh的脚本,用于说明它:

#!/bin/bash
$@ &
pid=$!

#kill -STOP $pid

echo "PID = $pid"
echo '$@  = '"$@"

ps -p $pid -o uname,pid,command
echo
ps -A -o uname,stat,command | grep 'script.sh' | grep -v grep

#kill -CONT $pid
wait $pid

exit 0

kill命令已被注释掉,这是有意的。会发生什么:

  • 我以另一个脚本作为参数启动该脚本:./test.sh ./script.sh
  • test.sh启动./script.sh,记录其PID显示信息
  • 信息显示子PID和与./script.sh对应的过程


    root@test# ./test.sh ./script.sh
    PID = 53370
    $@  = ./script.sh
    USER        PID   COMMAND
    root      53370   /bin/bash ./script.sh                  <-- Child process
    
    USER      PID    STAT   COMMAND
    root      53369  S+     /bin/bash ./test.sh ./script.sh  <-- Current process
    root      53370  S+     /bin/bash ./script.sh            <-- Child process

一切正常。

现在,如果我取消注释kill命令,该脚本将显示以下信息:



    root@test# ./test.sh ./script.sh
    PID = 53422
    $@  = ./script.sh
    USER        PID   COMMAND
    root      53422   /bin/bash ./test.sh ./script.sh          <-- Child process
    
    USER      PID    STAT   COMMAND
    root      53421  S+     /bin/bash ./test.sh ./script.sh    <-- Current process
    root      53422  T+     /bin/bash ./test.sh ./script.sh    <-- Child process

我不确定为什么当我暂停子进程时,我的 current 进程和 child 会得到完全相同的COMMANDps输出中处理。

为什么会这样?我想了解这种情况下父进程和子进程之间的机制。

解决方法

因为您已经停止了在fork()execve()之间的孩子,然后才能够执行script.sh脚本。

sleep 1之前添加kill -STOP,以查看效果。

fork()将子级创建为父进程的副本(这意味着它将在ps输出中以相同的进程名称,命令行参数显示,以及除pid之外的几乎所有其他内容)。当子级调用execve()系统调用时,它将替换所有这些。

fork()之后,不能保证首先运行父级或子级(实际上,它们可以在单独的处理器上同时运行,或者可以无限期抢占它们中的任何一个)- -以及从它们彼此执行不同操作的顺序中得出的任何“哲学”结论都是毫无意义的;-)