我面临一个关于向init进程(PID 1)发送信号9(SIGKILL)的奇怪问题。 您可能知道,SIGKILL不能通过信号处理程序忽略。当我尝试向SIG发送SIGKILL时,我发现没有发生任何事情; init不会被终止。试图弄清楚这种行为,我决定将自己附加到使用strace的init进程,也可以更清楚地看到发生了什么。现在是奇怪的部分。如果我正在使用strace“查看”init进程并将其发送给SIGKILL,则系统崩溃。
我的问题是为什么会发生这种情况?为什么在我查看流程时系统崩溃,为什么在我不这样做时它不会崩溃?正如我所说,在这两种情况下我都将SIGKILL发送给init。在CentOS 6.5,Debian 7和Arch。上进行了测试。
谢谢!
答案 0 :(得分:6)
如果init
终止,Linux内核会故意强制系统崩溃(请参阅http://lxr.free-electrons.com/source/kernel/exit.c?v=3.12#L501,特别是其中panic
的调用)。因此,作为安全措施,内核不会向init
发送任何致命信号,并且SIGKILL
不会被排除(请参阅http://lxr.free-electrons.com/ident?v=3.12&i=SIGNAL_UNKILLABLE)(但是,代码流程很复杂,我不确定,但我怀疑内核生成的SIGSEGV
或类似的东西会通过)。
将ptrace(2)
(strace
使用的系统调用)应用于进程1显然会禁用此保护。这可以说是内核中的一个错误。我没有足够的技巧去挖掘代码中找到这个bug。
我不知道其他Unix变体是否对init
应用了相同的崩溃退出语义或信号保护。如果init
终止(至少,如果通过调用_exit
这样做),让操作系统执行干净关机或重启,而不是恐慌是合理的,但据我所知,所有现代Unix变体都有一个专门的系统调用来请求它,而不是(reboot(2)
)。