zoukankan      html  css  js  c++  java
  • Kill杀死Linux中的defunct进程(僵尸进程)

    一、什么是defunct进程(僵尸进程)?
    在 Linux 系统中,一个进程结束了,但是他的父进程没有等待(调用wait / waitpid)他,那么他将变成一个僵尸进程。当用ps命令观察进程的执行状态时,看到这些进程的状态栏为defunct。僵尸进程是一个早已死亡的进程,但在进程表(processs table)中仍占了一个位置(slot)。
    但是如果该进程的父进程已经先结束了,那么该进程就不会变成僵尸进程。因为每个进程结束的时候,系统都会扫描当前系统中所运行的所有进程,看看有没有哪个进程是刚刚结束的这个进程的子进程,如果是的话,就由Init进程来接管他,成为他的父进程,从而保证每个进程都会有一个父进程。而Init进程会自动wait其子进程,因此被Init接管的所有进程都不会变成僵尸进程。

    二、 Linux下进程的运作方式
    每个 Linux进程在进程表里都有一个进入点(entry),核心进程执行该进程时使用到的一切信息都存储在进入点。当用 ps 命令察看系统中的进程信息时,看到的就是进程表中的相关数据。当以fork()系统调用建立一个新的进程后,核心进程就会在进程表中给这个新进程分配一个进入点,然后将相关信息存储在该进入点所对应的进程表内。这些信息中有一项是其父进程的识别码。
    子进程的结束和父进程的运行是一个异步过程,即父进程永远无法预测子进程到底什么时候结束。那么会不会因为父进程太忙来不及 wait 子进程,或者说不知道子进程什么时候结束,而丢失子进程结束时的状态信息呢?
    不会。因为 Linux提供了一种机制可以保证,只要父进程想知道子进程结束时的状态信息,就可以得到。这种机制就是:当子进程走完了自己的生命周期后,它会执行exit()系统调用,内核释放该进程所有的资源,包括打开的文件,占用的内存等。但是仍然为其保留一定的信息(包括进程号the process ID,退出码exit code,退出状态the terminationstatus of the process,运行时间the amount of CPU time taken by the process等),这些数据会一直保留到系统将它传递给它的父进程为止,直到父进程通过wait / waitpid来取时才释放。
    也就是说,当一个进程死亡时,它并不是完全的消失了。进程终止,它不再运行,但是还有一些残留的数据等待父进程收回。当父进程 fork() 一个子进程后,它必须用 wait() (或者 waitpid())等待子进程退出。正是这个 wait() 动作来让子进程的残留数据消失。
    三、僵尸进程的危害
    如果父进程不调用wait / waitpid的话,那么保留的那段信息就不会释放,其进程号就会一直被占用,但是系统的进程表容量是有限的,所能使用的进程号也是有限的,如果大量的产生僵尸进程,将因为没有可用的进程号而导致系统不能产生新的进程。
    所以,defunct进程不仅占用系统的内存资源,影响系统的性能,而且如果其数目太多,还会导致系统瘫痪。而且,由于调度程序无法选中Defunct 进程,所以不能用kill命令删除Defunct 进程,惟一的方法只有重启系统。
    四、如何杀死defunct进程
    defunct进程是指出错损坏的进程,父子进程之间不会再通信。有时,它们会演变成“僵尸进程”,存留在你的系统中,直到系统重启。可以尝试 “kill -9” 命令来清除,但多数时候不管用。
    为了杀死这些defunct进程,你有两个选择:
    1.重启你的计算机
    2.继续往下读…
    我们先看看系统中是否存在defunct进程:

    $ ps -A|grep defunct
    

    输出

    5259 ?        00:00:00 sd_cicero <defunct>
    12214 pts/18   00:01:14 python <defunct>
    16989 pts/18   00:04:43 python <defunct>
    20610 pts/18   00:23:12 python <defunct>
    

    看看这些进程的ID及其父进程ID:

    $ ps -ef | grep defunct | more
    
    UID PID PPID ...
    ==========================================================================
    yourname     4653  6128  0 17:07 pts/18   00:00:00 grep --color=auto defunct
    yourname     5259  5258  0 15:58 ?        00:00:00 [sd_cicero] <defunct>
    yourname    12214 12211  4 16:41 pts/18   00:01:14 [python] <defunct>
    yourname    16989 16986 20 16:45 pts/18   00:04:43 [python] <defunct>
    yourname    20610 18940 99 16:48 pts/18   00:23:12 [python] <defunct>
    

    UID:用户ID
    PID:进程ID
    PPID:父进程ID

    如果你使用命令 “kill -9 12214” 尝试杀死ID为12214的进程,可能会没效果。
    我们来试一下

    $ kill -9 12214
    $ ps -A|grep defunct
    

    输出

     5259 ?        00:00:00 sd_cicero <defunct>
    12214 pts/18   00:01:14 python <defunct>
    16989 pts/18   00:04:43 python <defunct>
    20610 pts/18   00:23:12 python <defunct>
    

    进程12214 仍然存才,说明用kill杀不掉它。

    要想成功杀死该进程,需要对其父进程(ID为12211)执行kill命令($ kill -9 12211)。对所有这些进程的父进程ID应用kill命令,并验证结果($ ps -A | grep defunct)。
    我们来试一下

    $ kill -9 12211
    $ ps -A|grep defunct
    

    输出

    5259 ?        00:00:00 sd_cicero <defunct>
    16989 pts/18   00:04:43 python <defunct>
    20610 pts/18   00:23:12 python <defunct>
    [1]   Killed                  bash main.sh
    

    进程12214消失,说明可以通过kill僵尸进程的父进程来杀死僵尸进程。

    如果前一个命令显示无结果,那么搞定!否则,可能你需要重启一下系统。

  • 相关阅读:
    对象池使用时要注意几点
    Flash3D学习计划(一)——3D渲染的一般管线流程
    714. Best Time to Buy and Sell Stock with Transaction Fee
    712. Minimum ASCII Delete Sum for Two Strings
    647. Palindromic Substrings(马拉车算法)
    413. Arithmetic Slices
    877. Stone Game
    338. Counting Bits
    303. Range Sum Query
    198. House Robber
  • 原文地址:https://www.cnblogs.com/vercont/p/10210194.html
Copyright © 2011-2022 走看看