问题描述
我在脚本中有这段代码。这是一个名为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
命令已被注释掉,这是有意的。会发生什么:
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 会得到完全相同的COMMAND
值ps
输出中处理。
为什么会这样?我想了解这种情况下父进程和子进程之间的机制。
解决方法
因为您已经停止了在fork()
和execve()
之间的孩子,然后才能够执行script.sh
脚本。
在sleep 1
之前添加kill -STOP
,以查看效果。
fork()
将子级创建为父进程的副本(这意味着它将在ps
输出中以相同的进程名称,命令行参数显示,以及除pid之外的几乎所有其他内容)。当子级调用execve()
系统调用时,它将替换所有这些。
在fork()
之后,不能保证首先运行父级或子级(实际上,它们可以在单独的处理器上同时运行,或者可以无限期抢占它们中的任何一个)- -以及从它们彼此执行不同操作的顺序中得出的任何“哲学”结论都是毫无意义的;-)