我运行该程序yes
并按Ctrl+Z来停止该进程。
之后,我通过执行将其唤醒kill -s 18 <pid>
。
此后,我无法再使用Ctrl+停止它Z或使用Ctrl+将其杀死C。这是为什么?
答案1
这都是关于 shell 和终端如何协作管理前台和后台进程。事情是这样的:
您yes
在交互式 shell 中运行。shellyes
在单独的进程组1中生成。shell 通知终端(终端仿真器)新进程组现在位于前台。术语是前台进程组。shell 保留在其自己的进程组中,不再是前台进程组。shell 停止从终端读取数据,实际上是将其自身置于后台。
当Ctrl+Z终端发送SIGSTP
到前台进程组。Ctrl+C类似:信号是SIGINT
,但它也转到前台进程组。
在您的例子中,SIGSTP
被发送到yes
进程。进程停止,其父进程(即 shell)收到SIGCHLD
,因此它可以做出反应。shell 通过通知终端新的前台进程组是 shell 之一来做出反应。shell 恢复从终端读取。这样它就将自己置于前台。它打印提示并让您进行交互。
然后执行并发kill -s 18 …
送到SIGCONT
进程yes
2 。
收到后,SIGCONT
进程yes
继续运行。它仍然在后台,即它的进程组没有变成前台进程组。它像在前台时一样打印到控制台3。整个情况就像你把停止的yes
放到后台或像一开始bg
一样在后台运行它一样。yes &
shell 仍然在前台。您尝试使用Ctrl+Z和Ctrl+时C,终端不断向 shell发送SIGSTP
和。您的 shell 可能打印并重写了提示,但由于打印速度非常快(并且您的终端滚动速度非常快),您没有注意到。SIGINT
SIGINT
^C
yes
您可能没有注意到您可以在 shell 中键入命令。如果您键入fg
Enter,shell 会通知终端 的进程组yes
是新的前台进程组。shell 会将自身置于后台,就像您调用 之后一样yes
。然后您可以通过按+或+来发送SIGSTP
或SIGINT
进入该流程。yes
CtrlZCtrlC
尝试一下。
1简单 shell 或非交互式 shell(没有作业控制)可能会运行其进程组中的所有内容。yes
但您所经历的情况表明它是在单独的进程组中生成的。
2在 Linux 中,数字 18 的具体含义取决于体系结构(请参阅man 7 signal
)。根据您的描述,我可以判断它的含义SIGCONT
(您可以通过检查 的输出来确认这一点kill -l
)。一般来说POSIX 将一些数字与特定信号联系起来,但 18 不在这些数字中,也不SIGCONT
在这些信号中。最便携的发送方式SIGCONT
是使用kill -s CONT
,而不是使用数字。这应该适用于任何符合 POSIX 标准的(或几乎符合 POSIX 标准的)操作系统。
3后台进程通常可以向其控制终端写入数据,但无法从中读取数据。调查SIGTTOU
和SIGTTIN
详细情况,我这里就不多说了。