如何PIDs
分配启动前使用的进程在重启后被分配给进程的RHEL7?
概率是多少?PID
换句话说,从统计角度来看RHEL7
,将相同的PID
进程分配给机器重新启动后启动的进程(与PID
重新启动之前使用的进程相同)是多么可想而知。
编辑:
例子:在重新启动之前,存在 PID 544 的守护进程 A,机器重新启动,重新启动后,守护进程 A 启动,并获得分配的 PID 544。
答案1
如果 init 系统是确定性的,那么由该 init 系统启动的守护进程很可能会在重新启动时以相同的 pid 启动,因为每次启动都会运行相同的代码(尽管偶尔会随机化fsck
或selinux
重新标记或其他此类非-)每次启动代码)。
然而,systemd
在 RHEL7 上是不确定的:PID 按顺序分配,但systemd
可能跨多个内核并行运行任务,可能等待各种硬件或网络服务。让我们看看进程列表前后发生了什么:
$ ps axo pid,command | sort -n > before
$ sudo reboot
...
$ ps axo pid,command | sort -n > after
$ comm -12 before after | grep -v \\[
comm: file 1 is not in sorted order
comm: file 2 is not in sorted order
PID COMMAND
1 /usr/lib/systemd/systemd --switched-root --system --deserialize 21
745 /usr/lib/systemd/systemd-logind
864 /usr/sbin/NetworkManager --no-daemon
$
[
因此,这是两个具有相同 PID 的进程(除了明显的非随机化“PID eins”和标有 的内核线程)。在 30 次重新启动中记录了几乎相同的信息,它似乎systemd
非常擅长随机化 pid;在这些重新启动期间/usr/lib/systemd/systemd-logind
出现:
PID PERCENTAGE
733 5%
734 5%
737 15%
739 5%
743 5%
746 5%
748 5%
749 5%
752 10%
753 10%
755 5%
758 5%
760 5%
764 5%
771 5%
773 5%
数据是通过启动服务捕获的:
[Unit]
Description=recordpidorder
After=getty.target
[Service]
Type=oneshot
ExecStart=/root/pidandboots
[Install]
WantedBy=multi-user.target
运行:
#!/bin/bash
NF=/root/sequence
[[ ! -e "$NF" ]] && echo 0 > "$NF"
CUR=$(( 1 + $(< "$NF") ))
ps haxo pid,command > "/root/pidorder$CUR"
[[ $CUR -gt 30 ]] && mv /root/pidandboots /root/pidandboots.done
echo "$CUR" > "$NF"
reboot
一旦系统启动并运行,进程创建顺序将随机化,因为非@reboot
cron 作业触发、用户登录并运行各种不同的命令等。这将取决于系统、在其上创建了多少个 PID 等。
所以,是的,从统计上可以想象,守护进程将在使用 的 RedHat 系统上以相同的 PID 出现systemd
。然而,几率会根据硬件和系统提供的具体服务而有所不同。
答案2
简短回答
100%
(我并不是说它将是相同的图像,尽管 init 总是 PID=1。只是在进程死亡后,在某些时候它的 PID 将被重用。)
更长的答案
它们可以在重新启动之前重复使用。它们会进行计数,直到使用了所有可能的 PID,然后重新开始,避开正在使用的 PID。
重新启动时,它们会在 1 处重新启动(进程 init 始终为 1)。
这是一个适用于所有 Unix 的通用答案。
答案3
100% 确定重新启动后将重用给定的 PID,但不能保证给定程序在重新启动后将获得与重新启动之前相同的 PID(并且在大多数情况下,它不会)。
Linux 与其他 UNIX 系统一样,使用一种非常简单的方法来确定新创建的进程的 PID,它只是在上一个未使用的进程启动所使用的 PID 之后按数字顺序获取下一个进程。当它达到 指定的上限时/proc/sys/kernel/pid_max
,它再次从 1 开始。请注意,此 sysctl 是用户可调的,但从实际角度来看,它仅限制系统上的进程总数。
现在,该规则有一些特定的例外情况。启动时,无论您的系统使用什么init
(RHEL 上默认使用 systemd,但您可以在内核命令行上指定任意二进制文件)总是开始时为 PID 1。特别是在 Linux 上,PID 2 是总是 kthreadd
,它是负责启动所有其他内核线程的核心内核进程,并且许多很早就启动的内核线程在重新启动后通常也始终具有相同的 PID(例如,PID 4 几乎总是软中断处理程序线程对于 x86 系统上的 CPU 0),但这取决于系统的硬件配置。