关于java:Linux系统僵尸进程详解

33次阅读

共计 2450 个字符,预计需要花费 7 分钟才能阅读完成。

大安好,我是良许。

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

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)─┬─systemd-journal(952)
        ├─systemd-udevd(963)
        ├─systemd-oomd(1137)
        ├─systemd-resolve(1138)
        ├─systemd-userdbd(1139)─┬─systemd-userwor(12707)
        │                     ├─systemd-userwor(12714)
        │                     └─systemd-userwor(12715)
        ├─auditd(1140)───{auditd}(1141)
        ├─dbus-broker-lau(1164)───dbus-broker(1165)
        ├─avahi-daemon(1166)───avahi-daemon(1196)
        ├─bluetoothd(1167)

每个过程在零碎中都被调配了一个编号。在这所有的过程中,有个十分非凡的过程,它的 ID 号是 1。它是零碎在疏导过程中执行的第一个过程,PID 1 之后的每个后续过程都是它的后辈。

什么是僵尸过程?

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

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

然而,如果父过程先于子过程完结,则子过程成为孤儿过程。孤儿过程将被 init 过程(过程号为 1)领养,并由 init 过程对孤儿过程实现状态收集工作。

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

僵尸过程是怎么产生的?

后面曾经介绍了僵尸过程产生的原理,上面咱们通过代码来模仿僵尸过程的产生。

#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 秒钟就退出,在它退出之后,父过程还未昏迷,因而没人给子过程「收尸」,所以它就变成了僵尸过程。

如何杀死僵尸过程

对于一般过程,咱们能够通过应用 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,并且你还杀死了它,那么零碎将间接重启!

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


最初,最近很多小伙伴找我要Linux 学习路线图,于是我依据本人的教训,利用业余时间熬夜肝了一个月,整顿了一份电子书。无论你是面试还是自我晋升,置信都会对你有帮忙!

收费送给大家,只求大家金指给我点个赞!

电子书 | Linux 开发学习路线图

也心愿有小伙伴能退出我,把这份电子书做得更完满!

有播种?心愿老铁们来个三连击,给更多的人看到这篇文章

举荐浏览:

  • 干货 | 程序员进阶架构师必备资源免费送
  • 书单 | 程序员必读经典书单(高清 PDF 版)

正文完
 0