我在想是否有办法在运行应用程序之前,强制Linux使用某个特定的进程ID给它。我需要提前知道进程ID。
实际上,有一种方法可以实现这个需求。自内核3.3以来,在CONFIG_CHECKPOINT_RESTORE设置中(大多数发行版都已设置),存在/proc/sys/kernel/ns_last_pid文件,其中包含内核生成的最后一个pid。因此,如果要为派生程序设置PID,则需要执行以下操作:
完成!子进程将拥有您想要的PID。另外,请不要忘记解锁(使用LOCK_UN进行加锁)并关闭ns_last_pid。
您可以在我的博客这里查看C代码。
正如许多人已经建议的那样,您不能直接设置PID,但通常shell有知道最后一个分叉进程ID的工具。
例如,在bash中,您可以在后台运行可执行文件(附加&
),并在变量$!
中找到其PID。
示例:
$ lsof >/dev/null &
[1] 15458
$ echo $!
15458
sudo echo 1893 > /proc/sys/kernel/ns_last_pid; sleep 1000
(但是请记住,如果在echo和sleep命令之间的极短时间内出现另一个进程执行,您可能会得到一个PID为1895+的PID。我已测试了数百次,从未发生过这种情况。如果您想保证PID,您需要在写入文件后锁定该文件,执行sleep,然后按照Ruslan上面的建议解锁文件。)
sudo echo 1893 > /proc/sys/kernel/ns_last_pid
不起作用,因为写入文件的是Bash而不是 echo
。使用 echo 1893 | sudo tee /proc/sys/kernel/ns_last_pid
或以 root 用户身份运行 Bash 命令都可以。 - TheTechRobo the Nerd无法强制使用特定的PID来运行进程。正如维基百科所说:
进程ID通常按顺序分配,从0开始递增到系统到达的最大值。一旦达到此限制,分配将重新开始,并在300处增加。在Mac OS X和HP-UX中,分配将在100处重新开始。但是,对于这个和后续的传递,仍然分配给进程的任何PID都将被跳过。
execve
(在某些已知位置注册其pid)。我绝对会避免为此黑客攻击内核。 - Basile Starynkevitchfork()
来创建新的子进程,直到你得到所需的 PID 的子进程。记得经常调用 wait()
,否则你很快就会达到每个用户的进程限制。ns_last_pid
方法相比,它的优点是不需要 root 权限。/sbin/init
和可能的 /sbin/modprobe
等等...(更不用说 vfork
作为 fork
的一种变体) - Basile Starynkevitch从Linux 5.5开始,您可以通过将PID数组传递给clone3
系统调用,并分配给新进程,最多为每个嵌套的PID命名空间分配一个。从内部向外部。这需要在PID命名空间上具有CAP_SYS_ADMIN
或(自Linux 5.9以来)CAP_CHECKPOINT_RESTORE
。
如果您不关心PID命名空间,请使用大小为一的数组。
fork
的返回值或在子进程中在fork
和exec *
之间,甚至在exec *
之后)来传递不透明生成的PID就足够了? - David Foerster