bg 和 kill -CONT 之间的区别

jok*_*ker 1 linux kill background-process

我在前台运行一个应用程序,并通过点击CTRL+ Z(并停止)将其置于后台。为了让它重新运行,我运行了命令bg %1(这是它的 JOBSPEC)。

我想为什么不试着让它跑回来kill -CONT <PID>。所以,我跑去jobs -l获取它的 PID,并将这个 pid 与 kill 和 CONT 信号一起使用。

但是,该程序没有再次上线!jobs -l在用 CONT 尝试 kill 后报告它正在运行,但它不是(因为它是灰色的)。

我使用该命令查看了应用程序 PID ps,发现了两个具有不同 PID(和 status Tl)的相同命令。

然后我查看了使用相同的东西pstree,发现它们都在父进程下。父进程与列出的进程不同,jobs -l因为我放在后台的进程似乎启动了另一个程序。另一个程序似乎创建了子进程。

我注意到的总结如下:

  • 使用kill将 CONT 发送到父进程使程序运行。

  • 父进程 PID 与 报告的不同jobs -l。换句话说,我应该向其发送 CONT 信号的进程与我发现使用jobs -l.

  • 向父进程发送 CONT 不会对子进程应用相同的信号。

  • 使用该命令bg使进程返回运行状态,将 CONT 信号发送到父进程的所有子进程。

我的结论正确吗?如果是这样,那么这意味着使用该命令bg可以节省向每个相关进程发送 CONT 的时间。这是正确的吗?

编辑我从命令行调用并放在后台的主要应用程序是git difftool. 我正在谈论的另一个应用程序本身创建了新子项meld,我将其设置为用作 git 中的差异工具。

mos*_*svy 5

首先,jobs -l不列出进程,而是列出进程(又名作业)。每个进程组都有一个进程领导者,其进程 id (pid) 等于其进程组 id (pgid)。

为了向进程组中的所有进程发送信号,而不仅仅是向其领导者发送信号,您应该kill使用 pgid 的负数调用。这在 kill(2) 联机帮助页中有描述:

如果 pid 小于 -1,则将 sig 发送到进程组中 ID 为 -pid 的每个进程。

在 shell 中同样有效:

$ sh -c 'while echo -n 1; do sleep 1; done'
111^Z
[1]+  Stopped                 sh -c 'while echo -n 1; do sleep 1; done'
$ jobs -l
[1]+ 11046 Stopped                 sh -c 'while echo -n 1; do sleep 1; done'
$ kill -CONT 11046
   <nothing>
$ kill -CONT -11046
$ 11111111...
Run Code Online (Sandbox Code Playgroud)

现在,得出你的结论:

使用 kill 将 CONT 发送到父进程使程序运行。

正确的

父进程PID 与jobs -l 报告的PID 不同。换句话说,我应该向其发送 CONT 信号的进程与我使用 jobs -l 找到的进程不同。

错了,是同一个pid,也和它的pgid一样。

向父进程发送 CONT 不会对子进程应用相同的信号。

正确的

使用命令 bg 使进程返回运行状态,向父进程及其所有子进程发送 CONT 信号。

正确,但前提是父进程和子进程都在同一个进程组中。此外,它不会依次为每个进程调用 kill(2),它只是使用 pgid 的负数(= 进程组领导的 pid)调用一次,并依赖内核将信号路由到所有进程在那个组。