编写不当或性能不佳的程序可能会使僵尸进程潜伏在Linux计算机内部。了解如何创建僵尸,以及如何最终让僵尸安息。

进程状态如何在Linux上工作
当然,Linux必须跟踪计算机上运行的所有应用程序和守护程序。它执行此操作的方法之一是维护过程表。这是内核内存中的结构列表。每个进程在此列表中都有一个条目,其中包含有关它的一些信息。
每个过程表结构中都没有很多。它们包含进程ID,其他一些数据项以及指向该进程的进程控制块(PCB)的指针。
PCB包含Linux需要为每个过程查找或设置的许多细节。在创建过程的过程中,给定处理时间,PCB也将进行更新,最后销毁。
Linux PCB包含超过95个字段。它定义为称为的结构task_struct.h
,长度超过700行。PCB包含以下类型的信息:
- 处理状态:状态在下面描述。
- 进程号:它在操作系统中的唯一标识符。
- 程序计数器:下一次允许该进程访问CPU时,系统将使用该地址查找应执行的下一条指令。
- 寄存器:此进程使用的CPU寄存器列表。该列表可能包含累加器,索引寄存器和堆栈指针。
- 打开文件列表:与此过程关联的文件。
- CPU调度信息:用于确定该进程的CPU处理时间和频率。流程的优先级,指向调度队列的指针以及其他调度参数必须记录在PCB中。
- 内存管理信息:有关此进程正在使用的内存的详细信息,例如进程内存的开始和结束地址,以及指向内存页面的指针。
- I / O状态信息:进程使用的任何输入或输出设备。
“处理状态”可以是以下任意一种:
- R:正在运行或可运行的进程。运行意味着它正在接收CPU周期并执行。一个可运行的进程已准备就绪,可以运行并等待CPU插槽。
- S:一个睡眠过程。流程正在等待动作完成(例如输入或输出操作)或资源可用。
- D:该过程处于不间断的睡眠状态。它正在使用阻塞的系统调用,只有在系统调用完成后才能继续。与“睡眠”状态不同,处于该状态的进程在系统调用完成并且执行返回到该进程之前不会响应信号。
- T:由于已接收到
SIGSTOP
信号,因此进程已终止(停止)。它 仅响应 对SIGKILL
或SIGCONT
信号,其分别要么杀死进程,或指示其继续。从前台(fg
)切换到后台(bg)
任务。 - Z: 僵尸进程。当一个过程完成时,它不仅消失了。它可以释放正在使用的所有内存,并从内存中删除自身,但仍保留在工艺表和PCB中。其状态设置为
EXIT_ZOMBIE
,并通过SIGCHLD
信号通知其父进程子进程已完成。
在Zombie状态下, 创建子进程时,父进程会调用 wait()
函数系列之一。然后,它等待子进程中的状态更改。子进程是否已停止,继续或被信号杀死?它通过自然完成其代码而终止吗?
如果状态更改是一种状态更改,则意味着子进程已停止运行,则将读取其退出代码。然后,销毁孩子的PCB,并删除其在过程表中的条目。理想情况下,这一切都在眨眼间发生,并且僵尸状态的进程不会存在很长时间。
相关文章 如何在Linux上运行和控制后台进程
是什么导致Linux上的僵尸进程?
wait()
创建子进程时,写得不好的父进程可能不会调用该函数。这意味着没有人在监视子进程中的状态变化,并且该SIGCHLD
信号将被忽略。或者,可能是由于不良的编程或恶意的意图,另一个应用程序正在影响父进程的执行。
但是,如果父进程不在子进程中监视状态变化,则不会发生适当的系统内务处理。子进程终止时,不会删除PCB和进程表中的条目。这导致僵尸状态永远不会从PCB上移除。
僵尸确实会占用一些内存,但通常不会造成问题。进程表中的条目很小,但是在发布之前,进程ID无法重用。在64位操作系统上,这不太可能引起任何问题,因为PCB比工艺表条目大得多。
可以想象,大量的僵尸可能会影响可供其他进程使用的内存量。但是,如果您有那么多僵尸,那么父应用程序或操作系统错误就是一个严重的问题。
如何删除僵尸进程
您无法杀死僵尸进程,因为它已经死了。它不会对任何信号做出响应,因为它已从内存中删除了-无处发送SIGKILL
信号。您可以尝试将SIGCHLD
信号发送给父进程,但是如果子进程终止时它不起作用,那么现在也不大可能起作用。
唯一可靠的解决方案是杀死父进程。终止时,其子进程将被该init
进程继承,这是在Linux系统中运行的第一个进程(其进程ID为1)。
该init
进程定期执行必要的清理僵尸的操作,因此要杀死它们,您只需要杀死创建它们的进程即可。该top
命令是查看是否有僵尸的便捷方法。
输入以下内容:
top
该系统具有八个僵尸进程。我们可以 通过使用ps
命令并将其 通过管道列出来列出它们egrep
。同样,僵尸进程的状态标志为“ Z”,您通常还会看到“已失效”。
输入以下内容:
ps aux | egrep“ Z | defunct”
列出了僵尸进程。
与来回滚动浏览相比,这是一种发现僵尸进程ID的巧妙方法top
。我们还看到一个名为“ badprg”的应用程序产生了这些僵尸。
第一个僵尸的进程ID是7641,但是我们需要找到其父进程的进程ID。我们可以ps
再次使用 。我们将使用输出选项(-o
)告知ps
仅显示父级的进程ID,然后将其与ppid=
标志一起传递。
我们要查找的进程将使用-p
(process)选项指示,然后传入僵尸的进程ID。
因此,我们键入以下命令以查找进程7641的进程信息,但它将仅报告父进程的ID:
ps -o ppid = -p 7641
我们被告知父进程ID为7636。我们现在可以ps
再次使用它来交叉引用它 。
我们看到这与之前的父进程的名称匹配。要终止父进程,请在kill命令中使用SIGKILL选项,如下所示:
kill-SIGKILL 7636
根据父流程的所有者,您可能还需要使用sudo
。
僵尸并不可怕……
…除非他们陷入大群。没什么可担心的,只需重新启动即可清除它们。
但是,如果您发现某个应用程序或进程始终在生成僵尸,则应注意这一点。它很可能只是一个草率的程序,在这种情况下,也许有一个更新的版本可以在子进程处理后正确清理。