这个问题与以下问题密切相关如何从 shell“正确”启动应用程序但试图解决更具体的问题。如何从 shell 生成应用程序,从而使其成为另一个进程的子进程。这是我用两个图形举例说明的意思:
systemd-+-acpid
|-bash---chromium-+-chrome-sandbox---chromium-+-chrome-sandbox---nacl_helper
| | `-chromium---5*[chromium-+-{Chrome_ChildIOT}]
| | |-{Compositor}]
| | |-{HTMLParserThrea}]
| | |-{OptimizingCompi}]
| | `-3*[{v8:SweeperThrea}]]
| |-chromium
| |-chromium-+-chromium
| | |-{Chrome_ChildIOT}
| | `-{Watchdog}
| |-{AudioThread}
| |-3*[{BrowserBlocking}]
| |-{BrowserWatchdog}
| |-5*[{CachePoolWorker}]
| |-{Chrome_CacheThr}
| |-{Chrome_DBThread}
| |-{Chrome_FileThre}
| |-{Chrome_FileUser}
| |-{Chrome_HistoryT}
| |-{Chrome_IOThread}
| |-{Chrome_ProcessL}
| |-{Chrome_SafeBrow}
| |-{CrShutdownDetec}
| |-{IndexedDB}
| |-{LevelDBEnv}
| |-{NSS SSL ThreadW}
| |-{NetworkChangeNo}
| |-2*[{Proxy resolver}]
| |-{WorkerPool/1201}
| |-{WorkerPool/2059}
| |-{WorkerPool/2579}
| |-{WorkerPool/2590}
| |-{WorkerPool/2592}
| |-{WorkerPool/2608}
| |-{WorkerPool/2973}
| |-{WorkerPool/2974}
| |-{chromium}
| |-{extension_crash}
| |-{gpu-process_cra}
| |-{handle-watcher-}
| |-{inotify_reader}
| |-{ppapi_crash_upl}
| `-{renderer_crash_}
|-2*[dbus-daemon]
|-dbus-launch
|-dhcpcd
|-firefox-+-4*[{Analysis Helper}]
| |-{Cache I/O}
| |-{Cache2 I/O}
| |-{Cert Verify}
| |-3*[{DOM Worker}]
| |-{Gecko_IOThread}
| |-{HTML5 Parser}
| |-{Hang Monitor}
| |-{Image Scaler}
| |-{JS GC Helper}
| |-{JS Watchdog}
| |-{Proxy R~olution}
| |-{Socket Thread}
| |-{Timer}
| |-{URL Classifier}
| |-{gmain}
| |-{localStorage DB}
| |-{mozStorage #1}
| |-{mozStorage #2}
| |-{mozStorage #3}
| |-{mozStorage #4}
| `-{mozStorage #5}
|-gpg-agent
|-login---bash---startx---xinit-+-Xorg.bin-+-xf86-video-inte
| | `-{Xorg.bin}
| `-dwm-+-dwmstatus
| `-xterm---bash-+-bash
| `-pstree
|-systemd---(sd-pam)
|-systemd-journal
|-systemd-logind
|-systemd-udevd
|-wpa_actiond
`-wpa_supplicant
进程树将 chromium 和 firefox 显示为init
在引导时启动并具有PID 1
.但我想要实现的是将 firefox 和 chromium 作为dwm
.因此,我想要与您在weston
以下进程树的部分中看到的类似的行为,其中 Firefoxweston-desktop
作为其父进程:
systemd-+-acpid
|-bash---chromium-+-chrome-sandbox---chromium-+-chrome-sandbox---nacl_helper
| | `-chromium-+-3*[chromium-+-{Chrome_ChildIOT}]
| | | |-{Compositor}]
| | | |-{HTMLParserThrea}]
| | | |-{OptimizingCompi}]
| | | `-3*[{v8:SweeperThrea}]]
| | `-4*[chromium-+-{Chrome_ChildIOT}]
| | |-{CompositorRaste}]
| | |-{Compositor}]
| | |-{HTMLParserThrea}]
| | |-{OptimizingCompi}]
| | `-3*[{v8:SweeperThrea}]]
| |-{AudioThread}
| |-3*[{BrowserBlocking}]
| |-{BrowserWatchdog}
| |-5*[{CachePoolWorker}]
| |-{Chrome_CacheThr}
| |-{Chrome_DBThread}
| |-{Chrome_FileThre}
| |-{Chrome_FileUser}
| |-{Chrome_HistoryT}
| |-{Chrome_IOThread}
| |-{Chrome_ProcessL}
| |-{Chrome_SafeBrow}
| |-{Chrome_SyncThre}
| |-{CrShutdownDetec}
| |-{IndexedDB}
| |-{NSS SSL ThreadW}
| |-{NetworkChangeNo}
| |-2*[{Proxy resolver}]
| |-{WorkerPool/2315}
| |-{WorkerPool/2316}
| |-{WorkerPool/2481}
| |-{chromium}
| |-{extension_crash}
| |-{gpu-process_cra}
| |-{handle-watcher-}
| |-{inotify_reader}
| |-{renderer_crash_}
| `-{sandbox_ipc_thr}
|-2*[dbus-daemon]
|-dbus-launch
|-dhcpcd
|-gpg-agent
|-login---bash---startx---xinit-+-Xorg.bin-+-xf86-video-inte
| | `-{Xorg.bin}
| `-dwm-+-dwmstatus
| `-xterm---bash
|-login---bash---weston-launch---weston-+-Xwayland---4*[{Xwayland}]
| |-weston-desktop--+-firefox-+-firefox
| | | |-4*[{Analysis Helper}]
| | | |-{Cache2 I/O}
| | | |-{Cert Verify}
| | | |-{DNS Resolver #1}
| | | |-{DNS Resolver #2}
| | | |-2*[{DOM Worker}]
| | | |-{Gecko_IOThread}
| | | |-{HTML5 Parser}
| | | |-{Hang Monitor}
| | | |-{Image Scaler}
| | | |-{ImageDecoder #1}
| | | |-{ImageDecoder #2}
| | | |-{ImageDecoder #3}
| | | |-{JS GC Helper}
| | | |-{JS Watchdog}
| | | |-{Socket Thread}
| | | |-{Timer}
| | | |-{URL Classifier}
| | | |-{gmain}
| | | |-{localStorage DB}
| | | |-{mozStorage #1}
| | | |-{mozStorage #2}
| | | |-{mozStorage #3}
| | | |-{mozStorage #4}
| | | `-{mozStorage #5}
| | `-weston-terminal---bash---pstree
| `-weston-keyboard
|-systemd---(sd-pam)
|-systemd-journal
|-systemd-logind
|-systemd-udevd
|-tmux---bash
|-wpa_actiond
`-wpa_supplicant
一种可能的解决方案是使用nsenter
from util-linux
。我可以输入进程的命名空间dwm
并派生一个新的 firefox 进程,该进程将成为dwm
.然而,这似乎需要很多工作。有一些更简单的方法可以做到这一点吗?
答案1
您不能将一个进程作为 shell 的子进程启动,然后“重新设置其父进程”,以便另一个进程成为它的父进程。
因此,您需要使用显式启动子进程的父进程。
init
PID 1 是一个例外,进程可以成为它的子进程,因为它收集丢失其原始父进程的进程。
(对于 upstart,可以有多个init
进程,它们不共享 PID 1,但在其他方面角色非常相似。)
(另请参阅PR_SET_CHILD_SUBREAPER in man 2 prctl
)
答案2
你所要求的根本不可能。根据 Unix 和 Linux 的设计,内部进程管理init
成为所有父进程死亡的进程的父进程。这是因为进程必须有父进程(也是设计使然),并且 init 始终存在,因为如果init
死亡,系统就会关闭。但除此之外,不存在“重新养育”过程之类的事情。
编辑
然而:正如 lord.garbage 所指出的,有一个神秘的prctl()
系统调用非常酷,并且使得任何使用它的程序都不可移植。假设我们不在乎。使用该PR_SET_CHILD_SUBREAPER
选项wait()
不仅可以为自己的孩子(像以前一样)而且可以为他们的所有后代(如果他们的父母过早去世)。因此,使用此功能的进程可以init
为其后代承担 的角色。以下代码是概念证明:
#include <sys/prctl.h>
#include <sys/wait.h>
#include <unistd.h>
#include <stdio.h>
int
main (int argc, const char* const argv[], char* const envp[])
{
pid_t pid;
if (prctl(PR_SET_CHILD_SUBREAPER, 1, 0, 0, 0) < 0) {
perror("prctl");
return 4;
}
pid = fork();
if (pid < 0) {
perror("fork");
return 4;
}
if (pid == 0) {
// child
char* const argv[] = { "/usr/bin/konsole", "-e", "/bin/bash", NULL };
if (execve("/usr/bin/konsole", argv, envp) < 0) {
perror("execve");
}
}
// parent
while (1) {
pid_t wpid;
int s;
wpid = waitpid(-1, &s, 0);
if (wpid > 0) {
printf("child with pid %u has exited\n", wpid);
}
}
return 0;
}
在后台运行一些不需要 shell 参与的程序,退出 konsole,运行ps
,退出程序,看看会发生什么。替换konsole
为您想要的任何内容。
现在,为了实现您想要的目的,请使用prctl()
PoC 中的调用,然后execve()
使用 to dwm
。希望这dwm
wait()
适用于非特定儿童,以免他们最终成为僵尸。
最后说明:仍然没有“重新养育”这样的事情。即,您仍然不能任意将父进程分配给进程。
答案3
我不相信您可以将进程作为父进程发送到 dwm 进程。但是,如果您可以将屏幕或 shell 作为 dwm 的子进程启动,那么您可以将所需的进程重新设置为该进程。请参阅此链接了解详细信息:http://monkeypatch.me/blog/move-a-running-process-to-a-new-screen-shell.html