我知道PID 1是init。现在我想知道,我可以将 init 进程 ID 替换为另一个进程 ID,并为 PID 1 分配一个新进程吗?如果是的话我该怎么做?
答案1
启动时启动的第一个进程接收 PID 1。
启动时启动的第一个进程有一个任务:它必须直接或间接启动所有其他进程。所有进程最终都是它的后代,因为除了内核在启动时运行程序之外,创建进程的唯一方式是某个进程执行系统调用来创建新进程。
PID为1的进程有一个工作:如果一个进程在运行子进程时死亡,则子进程的父进程ID设置为1。当子进程死亡时,PID 1应该收割它们,即调用系统调用wait
,否则僵尸子进程的部分留在后面。
调用的各种程序init
(有多种实现)执行这两项工作。
Linux 内核有一个命令行参数来更改哪个可执行文件作为第一个进程执行²。它可用于运行任何可执行文件,但如果该可执行文件不执行 init 的工作,系统将无法正常运行。此功能主要用于进入系统修复模式,例如仅在控制台上运行外壳程序而不执行其他操作。
一旦系统正常启动,就不可能替换PID 1,因为init不会死掉。 init 不仅不会死掉,因为它被编程为永远运行(init 应该一直运行直到系统关闭),而且它甚至获得了特殊的保护,免受会杀死其他进程的信号(例如 SIGKILL)的影响。
Linux 有一个PID命名空间允许使用自己的一组进程 ID 定义子系统的功能。从命名空间内部和外部查看时,PID 命名空间中的进程具有不同的 PID。命名空间中的第一个进程在命名空间中获取 PID 1。在命名空间之外,它不会有 PID 1(除非 init 选择进入新的 PID 命名空间,但 init 不会这样做,因为这会阻止它完成其工作)。
1这并不完全正确,某些内核有其他方式来启动进程。例如,modprobe
当在某些情况下发现某些硬件时,Linux 就会启动。但 init 的后代占据了绝大多数进程。
²先于后初始化文件系统或者初始化程序。
答案2
正如 Gilles 所指出的, init 在某些方面很特别。如果 init 死掉,在大多数情况下你会遇到内核恐慌,这就是为什么任何有信誉的 init 作者都会做很多事情来避免这种情况的发生。另一方面,它与任何其他程序非常相似,除了处理僵尸进程之外,您实际上可以使用任何程序作为 init。 cat 工作得很好,但并不完全有用。 init 完全普通的方式之一是它可以调用 execlve(exec 和朋友),它使用相同的 pid 将一个程序替换为另一个程序。例如,初始根磁盘使用它在安装要运行的驱动器后运行真正的 init。