• linux 僵尸进程处理


    什么是僵尸进程

    我们启动一个程序,开始我们的任务,然后等任务结束了,我们就停止这个进程。 进程停止后, 该进程就会从进程表中移除。

    但是,有时候有些程序即使执行完了也依然留在进程表中。那么,这些完成了生命周期但却依然留在进程表中的进程,我们称之为 “僵尸进程”。

    它们是如何产生的

    当你运行一个程序时,它会产生一个父进程以及很多子进程。 所有这些子进程都会消耗内核分配给它们的内存和 CPU 资源。

    这些子进程完成执行后会发送一个 Exit 信号然后死掉。这个 Exit 信号需要被父进程所读取。父进程需要随后调用 wait命令读取子进程的退出状态,并将子进程从进程表中移除。

    若父进程正确第读取了子进程的 Exit 信号,则子进程会从进程表中删掉。

    但若父进程未能读取到子进程的 Exit 信号,则这个子进程虽然完成执行处于死亡的状态,但也不会从进程表中删掉。

    僵尸进程对系统有害吗

    不会。由于僵尸进程并不做任何事情, 不会使用任何资源也不会影响其它进程, 因此存在僵尸进程也没什么坏处。 不过由于进程表中的退出状态以及其它一些进程信息也是存储在内存中的,

    因此存在太多僵尸进程有时也会是一些问题,并且由于操作系统所能创建的最大进程数量是有限的(进程号被大量占用)会导致新的进程无法创建。

    找出僵尸进程

    通过top命令可以看到僵尸进程的数目

     在终端并输入下面命令会列出进程表中所有僵尸进程的详细内容。

    ps aux |grep Z

    如何杀掉僵尸进程

    正常情况下我们可以用 SIGKILL 信号来杀死进程,但是僵尸进程已经死了, 你不能杀死已经死掉的东西。 因此需要输入如下命令 

    kill -s SIGCHLD pid

    将这里的 pid 替换成父进程的进程 id,这样父进程就会删除所有以及完成并死掉的子进程了。

    不过许多程序写的不是那么完美,无法及时删掉这些子僵尸。 因此确保删除子僵尸的唯一方法就是杀掉它们的父进程。

     我们可以模拟一个僵尸进程的产生并找到它

    #include <unistd.h>
    #include <stdio.h>
    #include <stdlib.h>
    int main(void) {
        int i = 100;
        pid_t pid=fork();
        if(pid < 0) {
            perror("fork failed.");
            exit(1);
        }
        if(pid > 0) {
            printf("This is the parent process. My PID is %d.
    ", getpid());
            for(; i > 0; i--) {
                sleep(1);
            }
        }
        else if(pid == 0) {
            printf("This is the child process. My PID is: %d. My PPID is: %d.
    ", getpid(), getppid());
        }
        return 0;
    }
    View Code

     可以看到产生了一个僵尸进程

     可以通过如下命令找出所有僵尸进程的父进程,处理不了可以通过杀死父进程来清理僵尸进程。

    ps -eo ppid,stat |grep Z |awk '{print $1}' |sort |uniq

     一个正常的进程

    下面的 demo 中,父进程通过 wait() 等待子进程结束

    #include <sys/types.h>
    #include <sys/wait.h>
    #include <unistd.h>
    #include <stdio.h>
    #include <stdlib.h>
    int main(void) {
        pid_t pid;
        pid = fork();
        if (pid < 0) {
            perror("fork failed");
            exit(1);
        }
        if (pid == 0) {
            int i;
             for (i = 3; i > 0; i--) {
                printf("This is the child
    ");
                sleep(1);
             }
            exit(3);
        }
        else {
            int stat_val;
            wait(&stat_val);
             if (WIFEXITED(stat_val)) {
                 printf("Child exited with code %d
    ", WEXITSTATUS(stat_val));
             }            
        }
        return 0;
    }
    View Code


    作者:Outsrkem
    出处:https://www.cnblogs.com/outsrkem/
    本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

  • 相关阅读:
    入梦初醒
    工作杂记
    终于用上双屏了!
    工作杂记(ii)
    2008
    $this>$a与$this>aPHP学习笔记
    明天要开工了
    好的程序员如何被发现,如何证明你简历中所标榜的那些精通和能力?
    架构师的思考:性能优化到何处为止?选择的原则
    极具挑战的超级智力测验题
  • 原文地址:https://www.cnblogs.com/outsrkem/p/14664296.html
Copyright © 2020-2023  润新知