我正在使用Ubuntu 14.04,但我遇到了我似乎无法理解的行为:
yes
命令(在默认 shell 中:Bash)yes
jobs
。输出:[1]+ Stopped yes
kill -9 %1
停yes
。输出:[1]+ Stopped yes
jobs
。输出:[1]+ Stopped yes
这是在3.16.0-30-generic
并行虚拟机中运行的Ubuntu上。
为什么我的kill -9
命令没有终止yes命令?我认为SIGKILL不能被捕获或忽略?以及如何终止yes命令?
lcd*_*047 10
信号被挂起的进程阻塞。在终端中:
$ yes
...
y
y
^Zy
[1]+ Stopped yes
Run Code Online (Sandbox Code Playgroud)
在第二个终端中:
$ killall yes
Run Code Online (Sandbox Code Playgroud)
在第一个终端中:
$ jobs
[1]+ Stopped yes
$ fg
yes
Terminated
Run Code Online (Sandbox Code Playgroud)
但是SIGKILL
不能被屏蔽。killall -9 yes
从第二个终端做同样的事情会立即在yes
终端中给出:
[1]+ Killed yes
Run Code Online (Sandbox Code Playgroud)
因此,如果kill -9 %1
不立即终止进程,那么要么在进程运行bash
之前实际上不会发送信号fg
,要么在内核中发现了错误。
没有什么时髦的事情发生。这里没有内核错误。这是 Bourne Again shell 和多任务操作系统的完全正常行为。
要记住的是,一个进程会杀死自己,即使是响应SIGKILL
. 这里发生的事情是,Bourne Again shell在它刚刚告诉杀死自己的进程开始杀死自己之前就开始处理事情。
考虑一下从yes
停止点开始发生的事情,SIGTSTP
并且您刚刚kill
使用 Bourne Again shell执行了命令:
SIGKILL
到yes
进程。yes
进程计划运行并立即自行终止。您看到一件事而其他人看到另一件事的原因是两个准备运行的进程之间的简单竞赛,获胜者完全取决于机器与机器之间以及随着时间的推移而变化的事物。系统负载会产生影响,就像您的 CPU 是虚拟的一样。
在有趣的情况下,步骤#2 的细节是这样的:
kill
命令内部的一部分,它将作业表中的条目标记为需要在下一个可用点打印通知消息。kill
命令,并在打印提示之前再次检查它是否应该打印有关任何作业的通知消息。yes
进程还没有机会杀死自己,因此就 shell 而言,该作业仍处于停止状态。因此外壳会为该作业打印“已停止”作业状态行,并重置其通知挂起标志。yes
过程被安排并自行终止。要点是:
SIGKILL
并不神奇。当从内核模式返回到应用程序模式时,进程会检查挂起的信号,这发生在页面错误、(非嵌套)中断和系统调用结束时。唯一特别的是,内核不允许响应的动作SIGKILL
是立即和无条件的自杀之外的任何动作,并且不会返回到应用程序模式。重要的是,进程既需要进行内核到应用程序模式的转换,又需要被调度运行以响应信号。set -o notify
)。当 shell 下一次到达其执行周期中的某个点时,将打印它们,以查看是否有任何通知未决。 kill
,一旦由SIGCHLD
信号处理程序。这意味着如果 shell在重新调度以杀死自身的进程之前运行,则可以看到两条消息yes
;一个是“Stopped”消息,一个是“Killed”消息。/bin/kill
程序无法访问 shell 的内部作业表;所以你不会看到这样的行为/bin/kill
。通知挂起标志仅由SIGCHLD
处理程序设置一次。kill
的yes
过程从另一个外壳。 你的系统上可能会发生一些奇怪的事情,在我的系统上,无论有没有:你的食谱都可以很好地工作-9
:
> yes
...
^Z
[1]+ Stopped yes
> jobs
[1]+ Stopped yes
> kill %1
[1]+ Killed yes
> jobs
>
Run Code Online (Sandbox Code Playgroud)
获取 pid 并jobs -p
尝试将其杀死root
。
归档时间: |
|
查看次数: |
4392 次 |
最近记录: |