为了让大家更好的理解僵尸这个概念先给大家看下百度百科对僵尸的定义:

僵尸(Jiang Shi): 顾名思义,僵硬的尸体;又名跳尸、移尸。在中华民间传说中,特指人类死后,尸体因为阴气过重而变异而成的鬼怪,毫无人性,丧失理智,双手向前横着伸直展开,且用双腿不停跳跃,从而移动的行尸走肉,除了头部和四肢,身子其他部位难以运动。加上由于近代影视的设想,往往会拥有超自然力量,比如力大无穷、刀枪不入、抗腐化等;甚至会使用武器和武功攻击人类。

所以,僵尸已经死了,不可能被杀死,不存在再死一次的问题。死的对立面是活,死者已死。只有活着的人才可能被杀死。

什么是僵尸进程?

首先要明确一点,僵尸进程的含义是:子进程已经死了,但是父进程还没有回收(wait)它的一个中间状态,这个时候子进程是一个僵尸。正常情况下子进程挂了,父进程通过wait回收子进程资源,清理掉子进程的task_struct,释放子进程的PID。看下面一个代码:

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>int main()
{    pid_t pid, wait_pid;    int status;pid = fork();    if (-1 == pid)    {           perror("fork");        exit(1);    }       else if (0 == pid)    {           printf("child pid = %d\n", getpid());        pause();    }       else    {           wait_pid = waitpid(pid, &status, 0);        if (WIFSIGNALED(status))        {            printf("child process is killed by signal %d\n", WTERMSIG(status));        }        exit(0);    }    return 0;
}

编译后运行:

# gcc zombie_process.c -o zombie_process
# ./zombie_processchild
pid = 16904

用ps命令查看进程的状态:


杀死子进程16904:

# kill -2 16904

父进程打印如下:

child process is killed by signal 2

之后,子进程16904会消失,因为父进程执行到了waitpid,也知道了子进程是被信号2杀掉的。程序没有任何问题。

对代码稍作修改。

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>​int main()
{    pid_t pid, wait_pid;    int status;​    pid = fork();    if (-1 == pid)    {           perror("fork");        exit(1);    }       else if (0 == pid)    {           printf("child pid = %d\n", getpid());       pause();    }       else   {           while (1);    }​    return 0;
}

我们重新编译运行,通过ps查看进程的状态:


用同样的方法杀死子进程17022:

kill -2 17022

然而,当我们再次使用ps查看进程的状态时,看到了不一样的现象。我们发现17022成为一个僵尸,状态变为Z,名字上也加了一个棺材[],成为[zombie_process]:


僵尸进程不可能被杀死。

看到上面17022是个僵尸很不爽,所以我们想把它干掉,据说Linux有个信号9,就是SIGKILL,这个信号是神一般的存在,神挡杀神,佛挡杀佛,我们现在来用kill -9干掉17022:

kill -9 17022

再次使用ps查看进程的状态:

即使我们把17022用kill -9捅了好多刀,但是最后看17022还是僵尸,一直没有消失。因为僵尸已经是死了,它不可能再次被杀死,你给它捅一万刀,它也是个死人,不可能再次死! 僵尸不可能被杀死,因为它已经死了!只能等父进程用wait来清理尸体了。这个时候我们能够把僵尸清理掉的方法,就是杀死僵尸进程的父进程17021。

一个僵尸可以被杀死的假象!

下面的这个程序证明“僵尸可以被杀死”:

#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>​void *mythread(void *arg)
{    while (1);
}​int main()
{    int ret;    pthread_t tid;​    ret = pthread_create(&tid, NULL, mythread, NULL);    if (-1 == ret)    {           perror("pthread_create");        exit(1);    }​    usleep(1000);    pthread_exit(0);​    return 0;
}

在主线程里面,pthread_create()创建线程后,pthread_exit()退出。编译代码并运行:

#gcc zombie_thread.c -o zombie_thread -lpthread
#./zombie_thread

再打开一个终端,通过ps查看进程的状态,zombie_thread显示为一个僵尸:


这个时候我们来杀死17082这个僵尸:

kill -9 17082

我们会惊奇地发现,17082真的会从ps命令里面消失!


我们把时间轴拉回调用 kill -9 17082 之前。刚才我们“看起来”能杀死僵尸的本质原因是,当主线程17082调用pthread_exit()退出后,主线程17082的状态确实是僵尸了,但是该进程里面的17083线程,却没有死:

下面分别看下两个线程的状态:

17082

17083


17083是活着的,证明整个进程并没有挂。所以17082的退出,只是让整个进程 半死。 而由于ps命令的误会,17082凑巧又是整个进程的PID,它显示好像整个17082成了僵尸一样。

那么,根据POSIX标准关于信号(signal)的定义,当我们执行kill -9 17082(17082是17082和17083的TGID,也是整个进程用户态视角的PID)的时候,是要杀死整个17082进程的,所以这个时候17082被我们杀死,整个进程就都死了,这个时候,相当于执行到父进程的wait逻辑,导致僵尸消失。所以,在本例中,kill -9 17082看起来是"杀死了僵尸”,实际是杀死了17082整个进程(包括里面的每个线程),导致整个进程死。在此之前,整个进程实际还是活的。

讲了这么多,就是要告诉大家,写代码的时候, 一定要注意进程或者线程的回收问题,创建的每一个进程或者线程在代码的某个地方都要回收资源,有始有终,避免bug出现。

更多精彩视频、文章、嵌入式学习资料,微信关注公众号 『学益得智能硬件』

僵尸进程该怎么处理?相关推荐

  1. linux里面有mysql的僵尸进程_Linux的僵尸进程处理1

    Linux中有两种异常的进程: 1.孤儿进程:应用通过fork进程后,父进程被kill或者exit,该父进程的子进程被1号进程接管.linux内核启动时候回启动0号进程,启动完毕后0号进程就处于空闲状 ...

  2. Linux的僵尸进程

    僵尸进程的简单理解 linux中有几种进程状态,其中有一种特殊就是僵尸进程,个人理解是可以这样理解,就是我们 的子进程已经退出了,但是子进程退出了之后无家可归,就是一个飘移的孤魂野鬼一样,所以形象的取 ...

  3. 如何查找僵尸进程并Kill之,杀不掉的要查看父进程并杀之

    用ps和grep命令寻找僵尸进程 #ps -A -ostat,ppid,pid,cmd | grep -e '^[Zz]' 命令注解: -A 参数列出所有进程 -o 自定义输出字段 我们设定显示字段为 ...

  4. c语言如何不产生僵尸进程,第三章 九析带你处理 zombie(defunct) 进程

    目录 1 前言 2 僵尸进程 2.1 进程简介 2.2 僵尸进程例子 2.3 僵尸进程危害 3 处理僵尸进程 3.1 kill 命令 3.2 kill 父进程 3.3 reboot 3.4 magic ...

  5. linux shell中清理僵尸进程

    2019独角兽企业重金招聘Python工程师标准>>> 今天登录到服务器上时,系统打印有6 zombie processes存在,于是用kill -9去清理掉这些僵尸进程,命令执行完 ...

  6. python3 多进程 multiprocessing对僵尸进程的处理

    之所以想写这么一篇博客,是在学TCP/IP网络编程时,讲到多进程服务器的构建时,父进程需要对子进程进行处理,不然的话会产生一堆的僵尸进程,最后会危害整个系统.然后想到我之前写的爬虫,Dwonloade ...

  7. docker 容器 defunct 僵尸进程

    在构建 Docker 容器时,我们需要注意子进程的"僵尸化"问题(PID 1 Zombie Reaping Problem).这会导致不可预知的和看起来匪夷所思的问题.本文解释了这 ...

  8. linux 僵尸进程 defunct

    在 Unix系统管理中,当用ps命令观察进程的执行状态时,经常看到某些进程的状态栏为defunct,这就是所谓的"僵尸"进程. "僵尸"进程是一个早已 死亡的进 ...

  9. 僵尸进程的生成以及几种避免方法

    #include <iostream> #include <unistd.h> #include <stdlib.h> using namespace std; i ...

  10. linux上寻找并杀死僵尸进程

    linux 服务器上,多少会出现一些 僵尸进程 ,下面介绍如何快速寻找和消灭这些僵尸进程的方法 首先,我们可以用top命令来查看服务器当前是否有僵尸进程,在下图中可以看到僵尸进程数的提示,如果数字大于 ...

最新文章

  1. 读《编程之道》-对于程序员的抽象描述
  2. SCCM 2007 R2部署、操作详解系列之部署篇
  3. oracle提供的有用函数(待续)
  4. 使用Entity Framework Core,Swagger和Postman创建ASP.NET Core Web API的分步指南
  5. WIZnet推出串口转以太网模块WIZ550S2E
  6. 安装特定版本的keras_一定要看的Tensorflow-GPU+Keras安装教程
  7. win10使用import pcap 建议放弃,还是使用linux系统吧
  8. Win11 可能解决Tomcat文件bin中startup打不开闪烁进不去的方法
  9. WDM驱动安装和卸载
  10. 产品经理的私房菜 - 腾讯产品模型 - 执行力篇
  11. 计算机演示文稿实验报告,演示文稿实验报告
  12. Jquery引用在线CDN公共资源库
  13. 声音信号 dB 及 dBA 的计算方式
  14. Windows系统解决谷歌翻译不能用的问题
  15. 2017河南工业大学校赛 C 魔法宝石
  16. 【读点论文】EfficientNetV2: Smaller Models and Faster Training 训练感知的神经架构搜索+自适应的渐近训练方法优化训练(TPU,大数据量)
  17. 视频压缩技术及安卓中用法
  18. qq修改实名认证已达上限_和平精英解除防沉迷怎么弄 和平精英实名认证修改教程...
  19. Windows 10 的中文用户名改成英文
  20. IntelliJ IDEA 2019.1.3 x64 简约基本配置

热门文章

  1. python 离线数据增强(扩充数据集)
  2. 手机地图哪个好?从老虎地图说开去(转帖)
  3. 转载!!!如何写出一份高逼格的简历 get√
  4. PC端QQ登录测试用例
  5. 复杂的POI导出Excel表格(多行表头、合并单元格)
  6. html页面设计成占满屏幕,关于html页面布局
  7. 均匀分布的公交站等车问题
  8. SpringCloud 服务注册与服务发现
  9. Add Configuration
  10. js随机从数组内取出一个值(整理)