如何在 Linux 上查找并杀死僵尸进程
僵尸是一种曾经是人类并死亡但由于病毒或任何原因再次醒来的生物。它已经死了,但仍在行走和移动。这就是电影和小说中描述的僵尸的概念。同样,在 Linux 中,僵尸进程是作为“已失效”从系统中删除但仍以某种方式在系统内存中运行的进程,称为僵尸进程。子进程在从进程表中被消除之前,首先会变成僵尸进程。
处于终止状态的进程是它的另一个名称。使用其父进程将其从内存中清除。当父进程没有收到变化通知时,子进程就成为僵尸进程,它不会得到任何终止信号,从而可以离开内存。在 Linux 中,每当一个进程从内存中删除时,其父进程都会收到有关删除的通知。该进程将保留在内存中,直到通知其父进程。
这意味着死亡进程不会立即从内存中删除,而是继续保留在系统内存中,从而成为僵尸进程。要删除僵尸进程,父进程调用 wait() 函数。一旦 wait() 函数被调用,僵尸进程就会从系统中完全删除。
杀死僵尸进程
在开始杀死僵尸进程之前,我们首先讨论一下僵尸进程的风险以及僵尸进程发生的原因。另外,我们还会详细了解僵尸进程,以便于理解查杀过程。
僵尸进程产生的原因是什么
僵尸进程可能有两个主要原因。第一个是子进程运行时父进程无法调用wait()函数,导致忽略SIGCHLD。这可能会导致僵尸进程。第二种是其他应用程序可能由于错误的编码或其中的恶意内容而影响父进程的执行。
换句话说,我们可以说,僵尸进程是由于父进程忽略了子进程状态的变化或者无法检查子进程的状态,当子进程结束时PCB没有被清除而引起的。
僵尸进程是否会带来风险
僵尸进程不会造成任何风险,它们只是使用系统中的部分内存。进程表很小,但存放僵尸进程的表id只有在被僵尸进程释放后才能使用。但如果有大量僵尸进程保留了内存位置,而没有剩余内存空间供其他进程使用,则其他进程将难以运行。
寻找僵尸进程
在杀死僵尸进程之前,有必要找到它们。要查找僵尸进程,我们将在终端中运行以下命令:
上面的命令中,“ps”代表进程状态,与 ps 命令一起用于查看系统中正在运行的进程的状态。我们传递了标志 aux,其中“a”表示终端中所有关联进程的详细信息,“u”表示用户列表中的进程,“x”表示不从终端执行的进程。结合起来,我们可以说它用于打印存储在内存中的所有正在运行的进程。
第二个选项“egrep”是一个处理工具,用于获取指定位置的表达式或模式。最后,我们传递了“Z|defunct”关键字,它表示要在内存中获取的僵尸进程。当我们执行该命令时,我们将得到以下输出,其中显示了系统中的僵尸进程及其“PID”。
输出:
linux 33819 0.0 0.0 18008 724 pts/0 S+ 20:22 0:00 grep -E --color=auto Z|defunct
僵尸进程已经是死进程,但父进程无法读取其状态,也无法从内存中释放。所以,死掉的进程是无法被杀死的。我们只能为它们做一些事情,使父进程能够读取子进程的状态,以便它可以被执行并从进程表中删除。为此,我们将运行下面提到的命令。
在上面的命令中,我们尝试获取僵尸进程的父ID。获取父进程 id 后,我们将运行以下命令,通过向父进程发送 SIGCHLD 来杀死僵尸进程,从而使父进程能够读取子进程的状态:
在上面的命令中,我们将信号传递给父id以杀死传递给它的父id的僵尸进程。执行上述命令后,如果不存在父 ID,它将简单地移动到下一行,而不在终端上打印任何输出。要检查僵尸进程是否被杀死,可以运行我们已经执行过的查找僵尸进程的命令。
让我们尝试另一种方法来杀死僵尸进程,即通过杀死父进程本身来完成。这是杀死僵尸进程的更有效方法,因为它将完全删除整个进程并且不会让僵尸再次出现。为此,我们将运行如下所示的命令:
运行上述命令后,我们允许系统杀死父进程。
结论
我们简要讨论了僵尸进程以及杀死这些进程的原因和程序。在开始我们的查杀过程之前,我们尝试解释其原因以及使用简单命令识别它们的方法。