精华内容
下载资源
问答
  • 僵尸进程
    千次阅读 多人点赞
    2021-10-12 03:52:47

    1、什么是僵尸进程和孤儿进程:

            在 Unix/Linux 系统中,正常情况下,子进程是通过父进程创建的,且两者的运行是相互独立的,父进程永远无法预测子进程到底什么时候结束。当一个进程调用 exit 命令结束自己的生命时,其实它并没有真正的被销毁,内核只是释放了该进程的所有资源,包括打开的文件、占用的内存等,但是留下一个称为僵尸进程的数据结构,这个结构保留了一定的信息(包括进程号 the process ID,退出状态,运行时间),这些信息直到父进程通过 wait()/waitpid() 来取时才释放。这样设计的目的主要是保证只要父进程想知道子进程结束时的状态信息,就可以得到

    • 僵尸进程:一个进程使用 fork 创建子进程,如果子进程退出,而父进程并没有调用 wait 或 waitpid 获取子进程的状态信息,那么子进程的进程描述符仍然保存在系统中,这种进程称之为僵死进程。

    • 孤儿进程:一个父进程退出,而它的一个或多个子进程还在运行,那么这些子进程将成为孤儿进程。孤儿进程将被 init 进程(进程号为1)所收养,并由 init 进程对它们完成状态收集工作。

    2、僵尸进程与孤儿进程的问题危害:

            僵尸进程虽然不占有任何内存空间,但如果父进程不调用 wait() / waitpid() 的话,那么保留的信息就不会释放,其进程号就会一直被占用,而系统所能使用的进程号是有限的,如果大量的产生僵死进程,将因为没有可用的进程号而导致系统不能产生新的进程,此即为僵尸进程的危害。

            孤儿进程是没有父进程的进程,孤儿进程这个重任就落到了 init 进程身上,init 进程就好像是一个民政局,专门负责处理孤儿进程的善后工作。每当出现一个孤儿进程的时候,内核就把孤儿进程的父进程设置为 init,而 init 进程会循环地 wait() 它的已经退出的子进程。这样,当一个孤儿进程凄凉地结束了其生命周期的时候,init 进程就会出面处理它的一切善后工作。因此孤儿进程并不会有什么危害。

    如果子进程在 exit() 之后,父进程没有来得及处理,这时用 ps 命令就能看到子进程的状态是“Z”。如果父进程能及时处理,可能用 ps 命令就来不及看到子进程的僵尸状态,但这并不等于子进程不经过僵尸状态。 如果父进程在子进程结束之前退出,则子进程将由 init 接管。init 将会以父进程的身份对僵尸状态的子进程进行处理。

    3、如果解决僵尸进程造成的问题:

    (1)方案一:父进程通过 wait 和 waitpid 等函数等待子进程结束,但这会导致父进程挂起,所以这并不是一个好办法,父进程如果不能和子进程并发执行的话,那我们创建子进程的意义就没有。同时一个 wait 只能解决一个子进程,如果有多个子进程就要用到多个 wait

    (2)方案二:通过信号机制:

            子进程退出时,向父进程发送 SIGCHILD 信号,父进程处理 SIGCHILD 信号,在信号处理函数中调用 wait 进行处理僵尸进程。

    (3)方案三:fork两次:

            原理是将进程成为孤儿进程,从而其的父进程变为 init 进程,通过 init 进程处理僵尸进程。具体操作为:父进程一次 fork() 后产生一个子进程随后立即执行 wait(NULL) 来等待子进程结束,然后子进程 fork() 后产生孙子进程随后立即exit(0)。这样子进程顺利终止(父进程仅仅给子进程收尸,并不需要子进程的返回值),然后父进程继续执行。这时的孙子进程由于失去了它的父进程(即是父进程的子进程),将被转交给Init进程托管。于是父进程与孙子进程无继承关系了,它们的父进程均为Init,Init进程在其子进程结束时会自动收尸,这样也就不会产生僵死进程了

    (4)方案四:kill 父进程:

            严格地来说,僵死进程并不是问题的根源,罪魁祸首是产生出大量僵死进程的那个父进程。因此,当我们寻求如何消灭系统中大量的僵死进程时,答案就是把产生大量僵死进程的那个元凶枪毙掉(也就是通过 kill 发送 SIGTERM 或者 SIGKILL 信号啦)。枪毙了元凶进程之后,它产生的僵死进程就变成了孤儿进 程,这些孤儿进程会被 init 进程接管,init 进程会 wait() 这些孤儿进程,释放它们占用的系统进程表中的资源,这样,这些已经僵死的孤儿进程就能瞑目而去了。

    参考文章:

    https://www.cnblogs.com/Anker/p/3271773.html

    https://www.cnblogs.com/jian-99/p/7739369.html

    更多相关内容
  • 本文主要给大家介绍了关于Linux中僵尸进程和孤儿进程的相关内容,分享给出来供大家参考学习,下面来看看详细的介绍: 1、僵尸进程 一个子进程在其父进程没有调用wait()或waitpid()的情况下退出,这个子进程就是僵尸...
  • 我们可以使用如下几种方法避免僵尸进程的产生: 1.在fork后调用wait/waitpid函数取得子进程退出状态。 2.调用fork两次(第一次调用产生一个子进程,第二次调用fork是在第一个子进程中调用,同时将父进程退出(第一...
  • 主要给大家讲解的是在Python中是如何产生僵尸进程的,以及如何清除僵尸进程的方法,有需要的小伙伴可以参考下
  • Linux 允许进程查询内核以获得其父进程的 PID,或者其任何子进程的执行状态。例如,进程可以创建一个子进程来执行特定的任务,然后调用诸如 wait() 这样的一些库函数检查子进程是否终止。如果子进程已经终止,那么,...
  • 主要介绍了Shell脚本实现查杀子进程、僵尸进程,本文直接给出实现代码,实现递归找到导致进程僵死的最底层子进程并杀除,需要的朋友可以参考下
  • dumb-init 跨框架init初始化进程,有效回收僵尸进程
  • Linux杀死僵尸进程.zip

    2021-01-07 19:13:29
    Linux杀死僵尸进程.zip 需要掌握的运维命令有ls、ps、free、top、uptime、ifconfig、susudo、dmesg、iostat、vmstat、sar、htop、iotop、smem等
  • 消除僵尸进程一般有5种方法,此处为其中的最常见最常用的两种
  • 主要介绍了PHP多进程编程之僵尸进程问题的理解的相关资料,希望通过本文能帮助到大家,让大家掌握这部分内容,需要的朋友可以参考下
  • 主要介绍了php多进程并发编程防止出现僵尸进程的方法,结合具体实例形式总结分析了php多进程并发编程防止出现僵尸进程相关操作技巧与注意事项,需要的朋友可以参考下
  • 僵尸进程以及如何处理僵尸进程

    千次阅读 2021-12-22 14:27:57
    僵尸进程:就是已经结束了的进程,但是没有从进程表中删除。太多了会导致进程表里面条目满了,进而导致系统崩溃,倒是不占用其他系统资源。最后有defunct的标记,就表明是僵尸进程。 今天配置Redis的时候结束停止...

    僵尸进程:就是已经结束了的进程,但是没有从进程表中删除。太多了会导致进程表里面条目满了,进而导致系统崩溃,倒是不占用其他系统资源。最后有defunct的标记,就表明是僵尸进程。
    在这里插入图片描述
    今天配置Redis的时候结束停止Redis服务的时候可能是误操作了,发生了上述的情况!

    产生的原因:

    每个Linux进程在进程表里都有一个进入点(entry),核心程序执行该进程时使用到的一切信息都存储在进入点。当用ps命令察看系统中的进程信息 时,看到的就是进程表中的相关数据。当以fork()系统调用建立一个新的进程后,核心进程就会在进程表中给这个新进程分配一个进入点,然后将相关信息存 储在该进入点所对应的进程表内。这些信息中有一项是其父进程的识别码。当这个进程走完了自己的生命周期后,它会执行exit()系统调用,此时原来进程表 中的数据会被该进程的退出码(exit code)、执行时所用的CPU时间等数据所取代,这些数据会一直保留到系统将它传递给它的父进程为止。由此可见,defunct进程的出现时间是在子进 程终止后,但是父进程尚未读取这些数据之前。

    Linux系统寻找和杀掉僵尸进程

    Linux服务器上,多少会出现一些僵尸进程,下面介绍如何快速寻找和消灭这些僵尸进程的方法:
    首先,可以使用top命令来查看服务器当前是否有僵尸进程,下图中可以看到僵尸进程的提示,如果数
    字大于0,那么意味着服务器当前存在僵尸进程:
    在这里插入图片描述
    我们发现存在33个僵尸进程!

    用ps 命令和 grep命令寻找僵尸进程:

    ps -A -ostat,ppid,pid,cmd | grep -e '^[Zz]'
    

    命令注解:

    • A 参数列出所有进程
    • o自定义输出字段,我们设定显示字段为stat(状态),ppid(父进程pid),pid(进程pid),cmd(命令行)这四个参数

    因为状态为 z 或者 Z的进程为僵尸进程,所以我们使用grep 抓取stat 状态为zZ进程;

    运行结果如下所示:
    在这里插入图片描述
    我这里直接杀死僵尸进程的父进程

    [root@songqixiang bin]# kill -9 31112
    

    在这里插入图片描述
    完事儿!

    展开全文
  • 僵尸进程和孤儿进程

    千次阅读 多人点赞 2022-01-05 15:45:26
      进程状态分为多种,有运行状态、浅度睡眠和深度睡眠状态、暂停状态、死亡状态,这些在小编的上...除此之外,还有僵尸进程、孤儿进程和守护进程,许多同学搞不懂僵尸进程和孤儿进程,这篇文章会详细为大家进行讲解。

      进程状态分为多种,有运行状态、浅度睡眠和深度睡眠状态、暂停状态、死亡状态,这些在小编的上一个博客中有所提到,如果对此有不懂的读者可以自行翻阅。除此之外,还有僵尸进程、孤儿进程和守护进程,许多同学搞不懂僵尸进程和孤儿进程,这篇文章会详细为大家进行讲解。

    一、僵尸进程

    1、僵尸进程的引出

      我们用小故事引出僵尸进程,从前有一个地主,他是一个守财奴,可有一天却暴毙于家中,府中的丫鬟发现后报官,知府中的捕快来到现场第一件事就是封锁现场,不让任何闲杂人入内,然后知府大人、捕快们入内勘察线索,来判断地主是死于他杀还是意外死亡,该怎么判断呢?通过现场留下的证据,以及地主体内器官、皮肤表面各种状态来进行分析判断。换一种情况,如果地主死后,府里的仆人们立马将案发现场收拾干净,将死者尸体入棺埋葬,此时再报案,衙门还能得出地主死亡的原因吗?–不能!只有捕快勘察现场,将死者进行分析后,其他人才能清理现场。

      上面的故事中,我们封锁现场,并采集证据的时候,死者此时是不能被移走或者清理的,此时死者就是处于僵尸状态。只有当我们采集完证据后才能清理现场,此时才算退出状态。

    那么为什么要存在僵尸进程呢?
      分析:进程被创建的目的就是完成某种工作或任务,当任务完成的时候,调用方应该知道创建的进程任务完成情况。
       举个最简单的例子,我们平时main函数中最后要写return 0;,这个0是做什么的呢?main函数是由mainCRTStartup函数调用的,mainCRTStartup是由加载器调用的,加载器又是由操作系统调用的,所以main函数间接性是OS调用的, 那么我们main函数是不是完成任务了,有没有异常退出,我们操作系统也是需要知道的,这里就需要给操作系统一个返回值,所以就有了return 0; 我们下面进行验证。我们学一个命令 - echo $?, $?用来检测最近一个进程执行完毕时的退出码信息(就是那个return值)。换言之,main函数的返回值就是供我们查看该进程的完成的状态。

    图一:proc.c
    图二:运行结果及退出码
    图一:proc.c
    图二:运行结果及退出码
       观察上方两个不同的代码,对应输出结果和退出码信息也在图中,我们发现,针对不同的情况,main函数返回给操作系统的退出码是不同的,其中0就代表进程正常结束,136则表明进程异常退出。

    经过以上分析,我们得出为什么要有僵尸进程。
      答:进程退出的信息(退出码),是会被暂时保存起来的(task_struct),如果没有人读取,此时,该task_struct相关数据就不应该被释放掉。这就是僵尸状态Z。(当有别人来读取我们的状态信息时,该僵尸进程才会被释放)

    2、模拟僵尸进程

      在下面的代码中,我们调用系统函数fork(),创建子进程之后,子进程会跑5秒钟,父进程一直在运行,子进程在5秒后退出,我们创建子进程就是让其帮我们去做某些事情的,但是子进程运行的怎么样,父进程是不知道的,父进程压根没管,所以就相当于子进程已经退出,父进程并不进行相关的状态询问,此时子进程虽然已经结束了,但是要一直维持一种状态—僵尸状态。

    图一:ZState.c
    图二:脚本查看进程状态
      我们发现, **当子进程结束的时候,其进程状态由S+变为Z+,这个状态就是僵尸状态。**

    3、总结

    3.1 僵尸进程概念

      僵尸状态(Zombies)是一个比较特殊的状态。当进程退出并且父进程没有读取到子进程退出的返回代码时就会产生僵尸进程,僵尸进程会以终止状态保持在进程表中,并且会一直在等待父进程读取退出状态代码。所以,只要子进程退出,父进程还在运行,但父进程没有读取子进程状态,子进程进入Z状态。关于父进程如何读取子进程的退出状态,我们后面再将。

    3.2 僵尸进程危害

      进程的退出状态必须被维持下去,因为他要告诉关心它的进程(父进程),你交给我的任务,我办的怎么样了。可父进程如果一直不读取,那子进程就必须一直处于Z状态!
      但是维护退出状态本身就是要用数据维护,也属于进程基本信息,所以保存在task_struct(PCB)中,换句话说,Z状态一直不退出,PCB就要一直维护!
      那一个父进程创建了很多子进程,就是不回收,就会造成内存资源的浪费!!因为数据结构对象本身就要占用内存。

    二、孤儿进程

      Linux系统中,进程之间的关系主要是符字关系,我们的僵尸进程就是父子进程之间,因为子进程退出,父进程不管他了,此时子进程就是僵尸进程。 我们的孤儿进程同样也是描述父子进程关系的。

    1、孤儿进程概念

      如果父进程先于子进程退出,此时子进程还在运行,那么此时的子进程就被称为孤儿进程。
      学习僵尸进程后我们知道一个进程退出后会产生退出码等信息,那么具有父子关系的进程之间,如果父进程先退出,导致子进程变为孤儿进程后,那这个孤儿进程不会永无止境的运行,他也会有退出的那一刻,他退出后也会变为僵尸进程,那么孤儿进程的退出码信息该怎么办呢?
      答:当一个进程变为孤儿进程后,这个进程会立即被系统领养。这个进程变为僵尸进程后,是由操作系统来回收的。(代表操作系统的进程1号进程)

    2、模拟孤儿进程

      我们修改之前模拟僵尸进程的代码,我们让父进程5s后退出,子进程变成死循环。
      下面就是程序和运行结果,我们在运行结果中发现子进程开始子进程的ppid是11013,而11013就是父进程的pid,当运行5s后,父进程退出,此时子进程的ppid变为1,这里就说明父进程退出后,子进程立马被1号进程收养,而1号进程就是操作系统。在进程状态图中我们也可以发现,

    图一:程序代码
    图二:运行结果

    3、总结

      孤儿进程:一个父进程退出,而它的一个或多个子进程还在运行,那么那些子进程将成为孤儿进程。
      孤儿进程将被init进程(进程号为1)所收养,并由init进程对它们完成状态收集工作。
      僵尸进程:一个进程使用fork创建子进程,如果子进程退出,而父进程并没有调用wait或waitpid获取子进程的状态信息,那么子进程的进程描述符仍然保存在系统中。这种进程称之为僵死进程。
      僵尸进程因为资源不会完全释放,因此有可能会造成资源泄漏,但是孤儿进程不会。

    在这里插入图片描述

    展开全文
  • 1、进程状态 top 和 ps 是最常用的查看进程状态的工具,我们就从 top 的输出开始。下面是一个 top 命令输出的示例,S 列(也就是 Status 列)表示进程的状态。从这个示例里,你可以看到 R、D、Z、S、I 等几个状态 $ ...

    1、进程状态

    top 和 ps 是最常用的查看进程状态的工具,我们就从 top 的输出开始。下面是一个 top 命令输出的示例,S 列(也就是 Status 列)表示进程的状态。从这个示例里,你可以看到 R、D、Z、S、I 等几个状态

    $ top
      PID USER      PR  NI    VIRT    RES    SHR S  %CPU %MEM     TIME+ COMMAND
    28961 root      20   0   43816   3148   4040 R   3.2  0.0   0:00.01 top
      620 root      20   0   37280  33676    908 D   0.3  0.4   0:00.01 app
        1 root      20   0  160072   9416   6752 S   0.0  0.1   0:37.64 systemd
     1896 root      20   0       0      0      0 Z   0.0  0.0   0:00.00 devapp
        2 root      20   0       0      0      0 S   0.0  0.0   0:00.10 kthreadd
        4 root       0 -20       0      0      0 I   0.0  0.0   0:00.00 kworker/0:0H
        6 root       0 -20       0      0      0 I   0.0  0.0   0:00.00 mm_percpu_wq
        7 root      20   0       0      0      0 S   0.0  0.0   0:06.37 ksoftirqd/0
    

    这几个状态的解释

    • R 是 Running 或 Runnable 的缩写,表示进程在 CPU 的就绪队列中,正在运行或者正在等待运行。
    • D 是 Disk Sleep 的缩写,也就是不可中断状态睡眠(Uninterruptible Sleep),一般表示进程正在跟硬件交互,并且交互过程不允许被其他进程或中断打断。
    • Z 是 Zombie的缩写,如果你玩过“植物大战僵尸”这款游戏,应该知道它的意思。它表示僵尸进程,也就是进程实际上已经结束了,但是父进程还没有回收它的资源(比如进程的描述符、PID等)。
    • S 是 Interruptible Sleep的缩写,也就是可中断状态睡眠,表示进程因为等待某个事件而被系统挂起。当进程等待的事件发生时,它会被唤醒并进入 R 状态。
    • I 是 Idle的缩写,也就是空闲状态,用在不可中断睡眠的内核线程上。前面说了,硬件交互导致的不可中断进程用 D表示,但对某些内核线程来说,它们有可能实际上并没有任何负载,用 Idle 正是为了区分这种情况。要注意,D 状态的进程会导致平均负载升高,I 状态的进程却不会。
    • 第一个是 T 或者 t,也就是 Stopped 或 Traced的缩写,表示进程处于暂停或者跟踪状态。
    • 向一个进程发送 SIGSTOP 信号,它就会因响应这个信号变成暂停状态(Stopped);再向它发送SIGCONT 信号,进程又会恢复运行(如果进程是终端里直接启动的,则需要你用 fg 命令,恢复到前台运行)。
    • 另一个是 X,也就是Dead 的缩写,表示进程已经消亡,所以你不会在 top 或者 ps 命令中看到它。

    2、僵尸进程

    僵尸进程,这是多进程应用很容易碰到的问题。正常情况下,当一个进程创建了子进程后,它应该通过系统调用 wait() 或者 waitpid() 等待子进程结束,回收子进程的资源;而子进程在结束时,会向它的父进程发送 SIGCHLD 信号,所以,父进程还可以注册 SIGCHLD 信号的处理函数,异步回收资源。

    如果父进程没这么做,或是子进程执行太快,父进程还没来得及处理子进程状态,子进程就已经提前退出,那这时的子进程就会变成僵尸进程。换句话说,父亲应该一直对儿子负责,善始善终,如果不作为或者跟不上,都会导致“问题少年”的出现。

    通常,僵尸进程持续的时间都比较短,在父进程回收它的资源后就会消亡;或者在父进程退出后,由 init 进程回收后也会消亡。

    一旦父进程没有处理子进程的终止,还一直保持运行状态,那么子进程就会一直处于僵尸状态。大量的僵尸进程会用尽 PID 进程号,导致新进程不能创建,所以这种情况一定要避免。

    3、案例分析排查

    在这里插入图片描述
    使用ps查看进程
    在这里插入图片描述
    从这个界面,我们可以发现多个 app 进程已经启动,并且它们的状态分别是 Ss+ 和 D+。其中,S 表示可中断睡眠状态,D 表示不可中断睡眠状态,我们在前面刚学过,那后面的 s 和 + 是什么意思呢?不知道也没关系,查一下 man ps 就可以。现在记住,s 表示这个进程是一个会话的领导进程,而 + 表示前台进程组。

    这里又出现了两个新概念,进程组和会话。它们用来管理一组相互关联的进程,意思其实很好理解。

    • 进程组表示一组相互关联的进程,比如每个子进程都是父进程所在组的成员;
    • 而会话是指共享同一个控制终端的一个或多个进程组。

    比如,我们通过 SSH 登录服务器,就会打开一个控制终端(TTY),这个控制终端就对应一个会话。而我们在终端中运行的命令以及它们的子进程,就构成了一个个的进程组,其中,在后台运行的命令,构成后台进程组;在前台运行的命令,构成前台进程组。

    小结:

    我们把这四个问题再汇总一下,就可以得到很明确的两点:

    • 第一点,iowait 太高了,导致系统的平均负载升高,甚至达到了系统 CPU 的个数。
    • 第二点,僵尸进程在不断增多,说明有程序没能正确清理子进程的资源。

    不可中断状态,表示进程正在跟硬件交互,为了保护进程数据和硬件的一致性,系统不允许其他进程或中断打断这个进程。进程长时间处于不可中断状态,通常表示系统有 I/O 性能问题。

    僵尸进程表示进程已经退出,但它的父进程还没有回收子进程占用的资源。短暂的僵尸状态我们通常不必理会,但进程长时间处于僵尸状态,就应该注意了,可能有应用程序没有正常处理子进程的退出。

    4、僵尸进程案例分析

    docker run --privileged --name=app -itd feisky/app:iowait
    
    # 间隔1秒输出10组数据
    $ dstat 1 10
    You did not select any stats, using -cdngy by default.
    --total-cpu-usage-- -dsk/total- -net/total- ---paging-- ---system--
    usr sys idl wai stl| read  writ| recv  send|  in   out | int   csw
      0   0  96   4   0|1219k  408k|   0     0 |   0     0 |  42   885
      0   0   2  98   0|  34M    0 | 198B  790B|   0     0 |  42   138
      0   0   0 100   0|  34M    0 |  66B  342B|   0     0 |  42   135
      0   0  84  16   0|5633k    0 |  66B  342B|   0     0 |  52   177
      0   3  39  58   0|  22M    0 |  66B  342B|   0     0 |  43   144
      0   0   0 100   0|  34M    0 | 200B  450B|   0     0 |  46   147
      0   0   2  98   0|  34M    0 |  66B  342B|   0     0 |  45   134
      0   0   0 100   0|  34M    0 |  66B  342B|   0     0 |  39   131
      0   0  83  17   0|5633k    0 |  66B  342B|   0     0 |  46   168
      0   3  39  59   0|  22M    0 |  66B  342B|   0     0 |  37   134
    

    pidstat查看进程的读写情况

    # -d 展示 I/O 统计数据,-p 指定进程号,间隔 1 秒输出 3 组数据
    $ pidstat -d -p 4344 1 3
    06:38:50      UID       PID   kB_rd/s   kB_wr/s kB_ccwr/s iodelay  Command
    06:38:51        0      4344      0.00      0.00      0.00       0  app
    06:38:52        0      4344      0.00      0.00      0.00       0  app
    06:38:53        0      4344      0.00      0.00      0.00       0  app
    

    去掉进程

    # 间隔 1 秒输出多组数据 (这里是 20 组)
    $ pidstat -d 1 20
    ...
    06:48:46      UID       PID   kB_rd/s   kB_wr/s kB_ccwr/s iodelay  Command
    06:48:47        0      4615      0.00      0.00      0.00       1  kworker/u4:1
    06:48:47        0      6080  32768.00      0.00      0.00     170  app
    06:48:47        0      6081  32768.00      0.00      0.00     184  app
    ...
    

    pstrace查看进程调用情况,对于僵尸进程无法查看调用情况

    $ strace -p 6082
    strace: attach: ptrace(PTRACE_SEIZE, 6082): Operation not permitted
    

    使用perf查看

    $ perf record -g
    $ perf report
    

    在这里插入图片描述

    查看某个僵尸进程的父进程

    # -a 表示输出命令行选项
    # p表PID
    # s表示指定进程的父进程
    $ pstree -aps 3084
    systemd,1
      └─dockerd,15006 -H fd://
          └─docker-containe,15024 --config /var/run/docker/containerd/containerd.toml
              └─docker-containe,3991 -namespace moby -workdir...
                  └─app,4009
                      └─(app,3084)
    

    僵尸进程处理

    而僵尸进程的问题相对容易排查,使用 pstree 找出父进程后,去查看父进程的代码,检查 wait() / waitpid() 的调用,或是 SIGCHLD 信号处理函数的注册就行了。

    1、查找僵尸进程
    ps -e -o stat,ppid,pid,cmd | egrep '^[Zz]'
    或者
    top 查看Z的进程
    或者
    ps -ef | grep defunct | more
    
    2、查找子进程对应的父进程
    pstree -aps 3084
    
    3、杀死对应的父进程
    kill -9 1024
    
    4、挂起子进程(还不如直接杀死父进程,子进程很多)
    [root@localhost ~]# kill -HUP 2481
    
    5、父进程中调用wait/waitpid函数

    当子进程终止时,内核就会向它的父进程发送一个SIGCHLD信号,父进程可以选择忽略该信号,也可以提供一个接收到信号以后的处理函数。对于这种信号的系统默认动作是忽略它。

    如果不希望有过多的僵尸进程产生,则需要在父进程接收到SIGCHLD信号后就应该调用 wait 或 waitpid 函数对子进程进行善后处理,释放子进程占用的资源。

    而当子进程在父进程之前终止时,内核为每个终止子进程保存了一定量的信息,所以当终止进程的父进程调用wait或waitpid时,可以得到这些信息。这些信息至少包括进程ID、该进程的终止状态、以及该进程使用的CPU时间总量。其他的进程所使用的存储区,打开的文件都会被内核释放。函数原型为:

    pid_t waitpid(pid_t pid, int *statloc, int options);
    

    若成功则返回进程ID,如果设置为非阻塞方式,返回0表示子进程状态未改变,出错时返回-1。

    options参数可以设置为WNOHANG常量,表示waitpid不阻塞,如果由pid指定的子进程不是立即可用的,则立即返回0。

    展开全文
  • 介绍什么是僵尸进程,以及如何处理僵尸进程
  • 在Linux系统中查看进程及杀死僵尸进程的方法.docx
  • Python处理僵尸进程

    千次阅读 2022-01-27 22:31:16
    os.waitpid、僵尸进程、python、signal
  • 僵尸进程 (1)进程中的指令已经执行完成,但是进程PCB结构还没有回收。 即子进程先于父进程退出后,子进程的PCB需要其父进程释放,但是父进程并没有释放子进程的PCB,这样的子进程就称为僵尸进程。 (2)父进程未...
  • 僵尸进程 僵尸进程讲解 核心: 孤儿进程 : 父进程先于子进程退出,此时子进程成为孤儿进程。 特点: 孤儿进程会被系统进程收养,此时系统进程就会成为孤儿进程新的父进程,孤儿进程退出该进程会自动处理。 僵尸...
  • Linux操作系统之孤儿进程和僵尸进程

    千次阅读 多人点赞 2022-06-13 21:49:42
    孤儿进程和僵尸进程是进程中常见的两种情况,今天我们来讲解一下
  • 今天在维护服务器的时候,发现有5个nova-novncproxy的僵尸进程。之前对于僵尸进程的了解并不深,赶紧找了篇相关文章来学习一下,该如何处理。定义In UNIX System terminology, a process that has terminated,but ...
  • Linux -- 多进程编程之 - 僵尸进程

    千次阅读 多人点赞 2021-11-04 22:23:15
    僵尸进程是当子进程比父进程先结束,而父进程又没有回收子进程,释放子进程占用的资源,此时子进程将成为一个僵尸进程
  • 这里写目录标题孤儿进程僵尸进程守护进程 孤儿进程 父进程如果不等待子进程退出,在子进程之前就结束了自己的“生命”此时的子进程叫做孤儿进程。init进程会收留孤儿进程,变成孤儿进程的父进程。 init 进程负责子...
  • 在fork()/execve()过程中,假设子进程结束时父进程仍存在,而父进程fork()之前既没安装SIGCHLD信号处理函数调用waitpid()等待子进程结束,又没有显式忽略该信号,则子进程成为僵尸进程,无法正常结束,此时即使是...
  • 小玲是一名数据库测试人员,这一天她尝试在docker环境中部署GreatDB集群,结果在对greatsqld进程进行kill操作后,意外发现greatsqld进程变成了僵尸进程(如下图所示)。 由于小玲成为测试人员的时间较短,她没有...
  • ‍♂️僵尸进程解决办法✅进程退出的两种情况✅再次理解僵尸进程产生原因✅进程等待,解决僵尸进程✔方法一`int wait(int *status);`如图不等待的情况等待的情况✔方法二`int waitpid(int pid, int *status, int ...
  • 僵尸进程介绍

    万次阅读 2021-03-02 23:32:36
    进程在它被创建的时刻开始存活,在 linux 系统中,这通常是调用 fork() 系统调用的结果,该系统调用通过复制一个现有进程来创建一个全新的进程。调用 fork() 的进程被称为父进程,新产生的进程被称为子进程。在该...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 48,923
精华内容 19,569
关键字:

僵尸进程