Bash: 为什么 kill -STOP 子进程使我的子进程和当前进程在 ps 中显示相同的命令行
Bash: why kill -STOP a child process makes my child and current process to show the same command line in 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,pid,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
并显示信息
- Infos显示子PID和一个进程对应
./script.sh
root@test# ./test.sh ./script.sh
PID = <b>53370</b>
$@ = ./script.sh
USER PID COMMAND
root <b>53370</b> <b>/bin/bash ./script.sh</b> <-- Child process
USER PID STAT COMMAND
root 53369 S+ /bin/bash ./test.sh ./script.sh <-- Current process
root <b>53370</b> S+ <b>/bin/bash ./script.sh</b> <-- Child process
一切正常。
现在,如果我取消注释 kill
命令,脚本会显示以下信息:
root@test# ./test.sh ./script.sh
PID = <b>53422</b>
$@ = ./script.sh
USER PID COMMAND
root <b>53422</b> <b>/bin/bash ./test.sh ./script.sh</b> <-- Child process
USER PID STAT COMMAND
root 53421 S+ /bin/bash ./test.sh ./script.sh <-- Current process
root <b>53422</b> T+ <b>/bin/bash ./test.sh ./script.sh</b> <-- Child process
我不确定为什么当我挂起我的子进程时,我的 当前 进程和我的 [=37] 得到完全相同的 COMMAND
值=]child 在 ps
输出中处理。
为什么会这样?我想了解这种情况下父进程和子进程之间的机制。
因为您在 fork()
和 execve()
之间停止了 child,然后才能执行 script.sh
脚本。
在kill -STOP
前加一个sleep 1
看看效果
A fork()
创建 child 作为 parent 进程的 copy(这意味着它将显示在 ps
输出具有相同的进程名称、命令行参数和除 pid 之外的几乎所有其他内容)。当 child 调用 execve()
系统调用时,它会替换所有这些。
在 fork()
之后,无法保证 parent 或 child 中的哪一个会首先 运行(事实上,他们可以 运行同时在不同的处理器上,或者它们中的任何一个都可以被无限期地抢占)——并且从它们彼此进行不同操作的顺序得出的任何“哲学”结论都是完全没有意义的;-)
我在脚本中有这段代码。这是一个名为 test.sh
的脚本来说明它:
#!/bin/bash
$@ &
pid=$!
#kill -STOP $pid
echo "PID = $pid"
echo '$@ = '"$@"
ps -p $pid -o uname,pid,command
echo
ps -A -o uname,pid,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
并显示信息- Infos显示子PID和一个进程对应
./script.sh
root@test# ./test.sh ./script.sh
PID = <b>53370</b>
$@ = ./script.sh
USER PID COMMAND
root <b>53370</b> <b>/bin/bash ./script.sh</b> <-- Child process
USER PID STAT COMMAND
root 53369 S+ /bin/bash ./test.sh ./script.sh <-- Current process
root <b>53370</b> S+ <b>/bin/bash ./script.sh</b> <-- Child process
一切正常。
现在,如果我取消注释 kill
命令,脚本会显示以下信息:
root@test# ./test.sh ./script.sh
PID = <b>53422</b>
$@ = ./script.sh
USER PID COMMAND
root <b>53422</b> <b>/bin/bash ./test.sh ./script.sh</b> <-- Child process
USER PID STAT COMMAND
root 53421 S+ /bin/bash ./test.sh ./script.sh <-- Current process
root <b>53422</b> T+ <b>/bin/bash ./test.sh ./script.sh</b> <-- Child process
我不确定为什么当我挂起我的子进程时,我的 当前 进程和我的 [=37] 得到完全相同的 COMMAND
值=]child 在 ps
输出中处理。
为什么会这样?我想了解这种情况下父进程和子进程之间的机制。
因为您在 fork()
和 execve()
之间停止了 child,然后才能执行 script.sh
脚本。
在kill -STOP
前加一个sleep 1
看看效果
A fork()
创建 child 作为 parent 进程的 copy(这意味着它将显示在 ps
输出具有相同的进程名称、命令行参数和除 pid 之外的几乎所有其他内容)。当 child 调用 execve()
系统调用时,它会替换所有这些。
在 fork()
之后,无法保证 parent 或 child 中的哪一个会首先 运行(事实上,他们可以 运行同时在不同的处理器上,或者它们中的任何一个都可以被无限期地抢占)——并且从它们彼此进行不同操作的顺序得出的任何“哲学”结论都是完全没有意义的;-)