Linux系统僵尸进程详解

Linux系统僵尸进程详解

大安好,我是良许。

本文我们将来讨论一下什么是僵尸进程,僵尸进程是怎么产生的,如何杀死一个僵尸进程。

Linux中的进程是什么?

讲到进程,我们要先了解一下另一个概念: 程序

程序说白了就是躺在电脑硬盘上的一个文件而已(如同硬盘女神一样),在被 CPU 执行之前,它啥也做不了。

当程序被执行之后,它运行的实例就称为 进程 。一个程序可以对应多个进程。

进程是系统的工作单元。系统由多个进程组成,其中有的是操作系统进程(执行系统代码),其他的是用户进程(执行用户代码)。所有这些进程都会并发执行,例如通过在单 CPU 上采用多路复用来实现。

你可以使用 ps 命令查看 Linux 系统中的所有进程 。

$ ps -ax
        PID TTY         STAT   TIME COMMAND
        1 ?     Ss      0:01 /usr/lib/systemd/systemd rhgb --switched-root --sys
        2 ?     S       0:00 [kthreadd]
        3 ?     I<      0:00 [rcu_gp]
        4 ?     I<      0:00 [rcu_par_gp]

当一个进程调用 fork 函数生成另一个进程,原进程就称为父进程,新生成的进程则称为子进程。

Linux 系统中这样父子进程非常多,我们可以使用 pstree 命令查看系统上的进程「谱系」。

$ pstree -psn
systemd(1)&#x2500;&#x252C;&#x2500;systemd-journal(952)
        &#x251C;&#x2500;systemd-udevd(963)
        &#x251C;&#x2500;systemd-oomd(1137)
        &#x251C;&#x2500;systemd-resolve(1138)
        &#x251C;&#x2500;systemd-userdbd(1139)&#x2500;&#x252C;&#x2500;systemd-userwor(12707)
        &#x2502;                     &#x251C;&#x2500;systemd-userwor(12714)
        &#x2502;                     &#x2514;&#x2500;systemd-userwor(12715)
        &#x251C;&#x2500;auditd(1140)&#x2500;&#x2500;&#x2500;{auditd}(1141)
        &#x251C;&#x2500;dbus-broker-lau(1164)&#x2500;&#x2500;&#x2500;dbus-broker(1165)
        &#x251C;&#x2500;avahi-daemon(1166)&#x2500;&#x2500;&#x2500;avahi-daemon(1196)
        &#x251C;&#x2500;bluetoothd(1167)

每个进程在系统中都被分配了一个编号。在这所有的进程中,有个非常特殊的进程,它的 ID 号是 1 。它是系统在引导过程中执行的第一个进程,PID 1 之后的每个后续进程都是它的后代。

什么是僵尸进程?

前面提到过,在 Linux 环境中,我们是通过 fork 函数来创建子进程的。创建完毕之后,父子进程独立运行,父进程无法预知子进程什么时候结束。

通常情况下,子进程退出后,父进程会使用 waitwaitpid 函数进行回收子进程的资源,并获得子进程的终止状态。

但是,如果父进程先于子进程结束,则子进程成为孤儿进程。孤儿进程将被 init 进程(进程号为1)领养,并由 init 进程对孤儿进程完成状态收集工作。

而如果子进程先于父进程退出,同时父进程太忙了,无瑕回收子进程的资源,子进程残留资源(PCB)存放于内核中,变成僵尸(Zombie)进程,如下图所示:

Linux系统僵尸进程详解

僵尸进程是怎么产生的?

前面已经介绍了僵尸进程产生的原理,下面我们通过代码来模拟僵尸进程的产生。

#include
#include
#include
#include

int main(void)
{
    pid_t pid;
    pid = fork();
    if (pid == 0) {
            printf("I am child, my parent= %d, going to sleep 3s\n", getppid());
            sleep(3);
            printf("-------------child die--------------\n");
    } else if (pid > 0) {
            printf("I am parent, pid = %d, myson = %d, going to sleep 5s\n", getpid(), pid);
            sleep(5);
            system("ps -o pid,ppid,state,tty,command");
    } else {
        perror("fork");
        return 1;
    }

    return 0;
}

在这个程序里,父进程创建子进程之后,就休眠 5 秒钟。而子进程只休眠 3 秒钟就退出,在它退出之后,父进程还未苏醒,因此没人给子进程「收尸」,所以它就变成了僵尸进程。

Linux系统僵尸进程详解

如何杀死僵尸进程

对于普通进程,我们可以通过使用 kill 命令来杀死它们。 kill 命令它还有几个兄弟,比如 pkillkillall ,虽然它们名称里都带 kill 这样杀气腾腾的字眼,但它们实际上是被设计为向一个或多个进程发送信号。

在未指定的情况下,这几个命令默认发送的是 SIGTERM 信号。

普通进程可以被 kill ,但僵尸进程是不行的。为什么?因为僵尸进程本身就已经「死」过一次了!如果还可以再「死」,那「僵尸」这个名号就没多大意义了。

僵尸进程其实已经就是退出的进程,因此无法再利用kill命令杀死僵尸进程。僵尸进程的罪魁祸首是父进程没有回收它的资源,那我们可以想办法它其它进程去回收僵尸进程的资源,这个进程就是 init 进程。

因此,我们可以直接杀死父进程,init 进程就会很善良地把那些僵尸进程领养过来,并合理的回收它们的资源,那些僵尸进程就得到了妥善的处理了。

例如,如果 PID 5878 是一个僵尸进程,它的父进程是 PID 4809,那么要杀死僵尸进程 (5878),您可以结束父进程 (4809):

$ sudo kill -9 4809  #4809 is the parent, not the zombie

杀死父进程时要非常小心,如果一个进程的父进程就是 PID 1 ,并且你还杀死了它,那么系统将直接重启!

这将是一个更可怕的故事!

Original: https://www.cnblogs.com/yychuyu/p/15553400.html
Author: 良许Linux
Title: Linux系统僵尸进程详解

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/611766/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

  • zenity,把shell加上图形界面

    有时自己写点小工具自己用,比较喜欢非图形界面的,可是有些应用还是弹出个东西来提醒一下,才能让你注意。 zenity是个很帅的东西,它用法可以参考它的–help ,这里不…

    Linux 2023年5月28日
    080
  • LeetCode-补充题9. 36进制加法

    题目来源 题目详情 36进制由0-9,a-z,共36个字符表示。 要求按照加法规则计算出任意两个36进制正整数的和,如1b + 2x = 48 (解释:47+105=152) 要求…

    Linux 2023年6月7日
    098
  • docker的基本使用

    一、 实验前置知识 Docker 是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的容器中,然后发布到任何流行的Linux机器上,也可以实现虚拟化。容器是…

    Linux 2023年6月13日
    068
  • MySQL半同步复制的实现和复制过滤器

    当客户端发送给服务端请求时,在等待服务端响应的时候,客户端可以做其他的事情,这样节约了时间,提高了效率。 当客户端发送请求给服务端,在等待服务端响应的请求时,客户端不做其他的事情。…

    Linux 2023年6月7日
    089
  • Vue 3-150行代码实现新国标红绿灯效果案例

    昨天刷视频,都是关于新国标红绿灯的,看大家议论纷纷,下班就用150行代码通过Vue组件实践红绿模拟演示,视频也跟大家展示过了。今天接着更新图文版本,大家跟着优雅哥通过该案例实操模拟…

    Linux 2023年6月7日
    076
  • Django基础学习笔记

    创建一个django项目:命令: django-admin startproject 项目名 进入到项目并创建一个应用:命令: python manage.py startapp …

    Linux 2023年6月6日
    087
  • 计算机系统实验

    实验三 一 实验目的 理解堆栈结构,利用缓冲区进行代码攻击 二 准备工作 配置实验环境(IDA、gcc),阅读实验指导书 三 实验过程 0x01第一关 首先理解堆栈的结构 /* 第…

    Linux 2023年6月8日
    089
  • vsftpd配置FTP服务器(Centos7.x安装)

    404. 抱歉,您访问的资源不存在。 可能是网址有误,或者对应的内容被删除,或者处于私有状态。 代码改变世界,联系邮箱 contact@cnblogs.com 园子的商业化努力-困…

    Linux 2023年6月7日
    076
  • Linux下无限期使用Navicat16

    原文链接:https://www.zhoubotong.site/post/79.htmllinux 下的数据库图形化工具比较好用的有dbeaver完全免费,相比navicat,我…

    Linux 2023年6月6日
    0138
  • 跨平台(32bit和64bit)的 printf 格式符 %lld 输出64位的解决方式

    在 C/C++ 开发中,使用 printf 打印 64 位变量比较常用,通常在 32 位系统中使用 %lld 输出 64 位的变量,而在 64 位系统中则使用 %ld; 如果在 3…

    Linux 2023年6月7日
    082
  • Linux专项之Apache

    1.&#x865A;&#x62DF;&#x673A;&#x4E0A;&#x7F51; 1.安装软件(httpd) yum search ht…

    Linux 2023年6月14日
    085
  • 【操作系统真象还原】04 编写MBR分区(二)和显卡对话

    前言 通过BIOS提供的中断,我们的MBR程序在屏幕上输出了绿油油的 Hi from MBR!。但只有在 &#x5B9E;&#x6A21;&#x5F0F; …

    Linux 2023年5月27日
    0131
  • 记一次burp suite文件上传漏洞实验

    一·文件上传漏洞概念文件上传漏洞是指 Web 服务器允许用户在没有充分验证文件名称、类型、内容或大小等内容的情况下将文件上传到其文件系统。未能正确执行这些限制可能意味着即使是基本的…

    Linux 2023年6月7日
    092
  • bash脚本-周末定时备份mysql数据库

    1.脚本如下 #usr/bin/sh #program:用于每周日定时备份全天候mysql文件 #author:sundz #version:v1 20220521 #定义文件夹和…

    Linux 2023年6月7日
    0100
  • Ansible简介

    Ansible 是一种常用的自动运维化工具,基于 python 开发,分布式,无需客户端,轻量级,配置语言采用 YAML。 模块化:调用特定的模块,完成特殊的任务。 2.Param…

    Linux 2023年6月6日
    089
  • 一面数据: Hadoop 迁移云上架构设计与实践

    背景 一面数据创立于 2014 年,是一家领先的数据智能解决方案提供商,通过解读来自电商平台和社交媒体渠道的海量数据,提供实时、全面的数据洞察。长期服务全球快消巨头(宝洁、联合利华…

    Linux 2023年6月14日
    0114
亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球