为什么 $$返回与父进程相同的 id?

我对巴斯有意见,我也不知道为什么。
在 shell 下面,我输入:

echo $$    ## print 2433
(echo $$)  ## also print 2433
(./getpid) ## print 2602

其中 getpid是一个 C 程序来获得当前的 Pid,如:

   int main() {
printf("%d", (int)getpid());
return 0;
}

让我困惑的是:

  1. 我认为“(命令)”是一个子过程(我说的对吗?),我认为它的 Pid应该与它的 家长会不同,但他们是一样的,为什么..。
  2. 当我用程序在括号之间显示 Pid时,它显示的 Pid是不同的,对吗?
  3. $$类似宏吗?

你能帮我吗?

319137 次浏览
  1. 括号调用 巴斯的子贝壳。因为它只是一个子 shell,所以它可能具有相同的 PID-取决于实现。
  2. 您调用的 C 程序是一个单独的进程,它有自己的唯一 PID ——不管它是否在子 shell 中。
  3. $$是 Bash 到 当前脚本 PID的别名。参见 在这里 ABC0和 $BASHPID之间的差异,以及正上方包含嵌套级别的附加变量 $BASH_SUBSHELL

$$定义为返回子 shell 中父进程的进程 ID; 来自“特殊参数”下的手册页:

$扩展到 shell 的进程 ID。在()子 shell 中,它扩展为当前 shell 的进程 ID,而不是子 shell。

bash4中,您可以使用 BASHPID获得子进程的进程 ID。

~ $ echo $$
17601
~ $ ( echo $$; echo $BASHPID )
17601
17634

如果希望 C 程序打印 shell 的 PID,请尝试 getppid()

您可以使用下列方法之一。

  • $!是最后一个背景进程的 PID。
  • kill -0 $PID检查它是否仍在运行。
  • $$是当前 shell 的 PID。

如果你问如何得到一个已知命令的 PID,它会像这样:

如果您发出以下命令 命令下达了

Dd if =/dev/diskx of =/dev/disky


然后你会用:

PIDs=$(ps | grep dd | grep if | cut -b 1-5)

这里发生的是它将所有需要的唯一字符传送到一个字段,并且该字段可以使用

Echo $PID

这是获得正确匹配值的唯一方法

pid=$(cut -d' ' -f4 < /proc/self/stat)

三明治也是这样

SUB(){
pid=$(cut -d' ' -f4 < /proc/self/stat)
echo "$$ != $pid"
}


echo "pid = $$"


(SUB)

检查输出

pid = 8099
8099 != 8100

如果需要一个简单的 shell 脚本来获得带有变量的最大 PID,可以这样做

pid=$(cat /proc/sys/kernel/pid_max)
echo $pid

将打印您的最大 PID 可以。

实现这一目标的便携式方法

get_own_pid() {
# This function being called in a subshell,
# it must returns the pid of the parent of the "cut" command parent
cut -d' ' -f4 < /proc/self/stat \
| xargs -I% sh -c 'cut -d" " -f4 < /proc/%/stat'
}


get_parent_pid() {
# Same thing but repeating the last command once more to get the parent one level above
cut -d' ' -f4 < /proc/self/stat \
| xargs -I% sh -c 'cut -d" " -f4 < /proc/%/stat' \
| xargs -I% sh -c 'cut -d" " -f4 < /proc/%/stat'
}




# Here pid is the same as the $$ pid because called from main process
MY_PID=$(get_own_pid)
echo "$$ == ${MY_PID}"


# Here called in a subprocess, the returned pid is different
(
MY_CHILD_PID=$(get_own_pid)
PARENT_PID_FROM_CHILD=$(get_parent_pid)
echo "$$ != ${MY_CHILD_PID}"
echo "$$ == ${PARENT_PID_FROM_CHILD}"
)

灵感来自 Artem Lapkin 回答,谢谢!