在Linux操作系统中,PID有可能被重用吗?
例如,一个 PID 名为 2252。该 PID 已失效并从内核进程表中删除。进程表是否有可能为新进程重新使用相同的 PID,或者它不会在任何即将到来的进程中使用?
答案1
当然。否则,系统每次启动只能运行 32768 个进程(或系统上的最大 pid 号)。
只要一个进程死亡并已被等待(如果父进程死亡,则由其父进程或子子收割者或 init 等待),其 pid 就可以重用。
您会看到脚本执行以下操作:
cmd1 & pid1=$!
something else
cmd2 & pid2=$!
more things
kill "$pid1" "$pid2"
这些是近似值,因为 shell(大多数 shell)语言没有为您提供任何更好的 API 来处理子进程。
如果这些进程可能已经死亡,则不能保证$pid1
和/或$pid2
仍会引用较早启动的进程。$pid1
并且$pid2
也可能是相同的(如果在开始cmd1
时已经死亡)。cmd2
所以kill
可能会杀死错误的进程。
实际上,这很少会成为问题,特别是在按顺序分配 pid 的系统上,因为 pid 数字需要相当长的时间才能换行。但当 pid 表变满时(例如当它充满僵尸进程时),一些攻击者可以利用这一点。
答案2
是的,可以重复使用。只是补充一下 Stéphane Chazelas 的答案:
如果您需要这个来编写脚本,例如您想要kill $PID
$PID 是单身的子进程,并且您不确定是否正在杀死正确的进程,那么至少在 bash 中您可以检查具有某些 $PID 的进程是否是当前 shell 的子进程,如下所示:
if grep -qFx $PID <(jobs -rp); then
kill $PID
fi
这里jobs -rp
打印子 PID,并grep -qFx $PID
在 $PID 匹配时返回 0。
当您需要区分单身的来自其他系统进程的子进程。但如果你想区分多种的对于当前 shell 的子级,您可能需要在每个子级退出时通知当前 shell。例如:
{
trap "echo $BASHPID >> exited" EXIT
# some long action
} &
这里,当子进程退出时,它将其PID写入文件exited
。主进程可以在杀死具有特定 PID 的进程之前检查它是否已经退出。
笔记。每次子进程退出时,SIGCHLD 信号都会发送到当前 shell。这可用于优化流程(例如trap "something..." SIGCHLD
)