【问题标题】:Zombie process vs Orphan process僵尸进程与孤儿进程
【发布时间】:2014-01-08 10:50:16
【问题描述】:

当父进程在子进程死亡后不使用等待系统调用来读取其退出状态时,就会创建一个僵尸,而当原始父进程在子进程之前终止时,一个孤儿进程是由 init 回收的子进程。

在内存管理和进程表方面,这些进程的处理方式有何不同,特别是在 UNIX 中?

什么是僵尸或孤儿的创建可能对更大的应用程序或系统有害的示例或极端情况?

【问题讨论】:

  • 制造大量僵尸并监视你的系统 ssssllooooowwww
  • 僵尸进程没有理由消耗(大量)内存......它已经死了。它基本上是一个占位符,以便父级在将来的某个时候仍然可以读取退出状态。
  • 僵尸没有占用任何显着的内存或资源,它(实际上)只是一个等待传递的退出状态。孤儿是一个活的、正在运行的进程,就像任何其他进程一样——它只是有一个特殊的名称。
  • @clintp 但是孤儿不能成为僵尸进程,因为一旦完成,操作系统就会处理它?
  • 如果init 进程中存在错误,或者阻止init 正常工作的内核错误,孤立的进程可能会变成僵尸。否则没有。但换个角度看,在父进程清理之前,每个退出的进程都是僵尸,所以是的,它们确实变成了僵尸,但不会持续很长时间。

标签: c unix fork zombie-process


【解决方案1】:

这是doc的一份摘要

Zombie Process Orphan Process
A Zombie is a process that has completed its task but still, it shows an entry in a process table. A child process that remains running even after its parent process is terminated or completed without waiting for the child process execution is called an orphan.
Zombie process states always indicated by Z The orphan process was created unknowingly due to a system crash.
The zombie process is treated as dead they are not used for system processing An orphan process is a computer process even after their parent terminates init is become a parent and continue the remaining task.
To remove the zombie process execute the kill command. Terminate the Orphan process using the SIGHUP signal.

另一个好的article列出一些场景。

【讨论】:

    【解决方案2】:

    僵尸进程: 已经完成执行但在进程表中仍有一个条目要报告给其父进程的进程称为僵尸进程。子进程在从进程表中删除之前总是首先成为僵尸。父进程读取子进程的退出状态,从进程表中获取子进程条目。

    孤儿进程: 父进程不存在的进程,即在没有等待其子进程终止的情况下完成或终止的进程称为孤儿进程。

    【讨论】:

      【解决方案3】:

      孤儿 - 父进程退出,初始化进程成为子进程的父进程。 每当 child 被终止时,进程表就会被 os 删除。

      僵尸 - 当孩子终止时,它会向父母提供退出状态。 同时假设您的父母处于睡眠状态并且无法从孩子那里收到任何状态。 子进程虽然退出,但进程占用进程表空间

      在 linux ubuntu 中查看这个命令 >>ps -eo pid,ppid,status,cmd

      如果你在最后发现类似 defunc 的东西,即你的进程是僵尸并占用空间。

      【讨论】:

        【解决方案4】:

        我想添加 2 个代码 sn-ps,其中包含一个孤立进程和一个僵尸进程。但首先,我将发布这些过程的定义,如 Silberschatz、Galvin 和 Gagn 所著的《操作系统概念》一书中所述:

        如果没有父等待(没有调用wait())进程是僵尸

        如果父进程没有调用 wait 就终止了,进程是一个孤儿

        孤儿

        // A C program to demonstrate Orphan Process.  
        // Parent process finishes execution while the 
        // child process is running. The child process 
        // becomes orphan. 
        
        #include <stdio.h>  //printf
        #include <stdlib.h> //exit
        #include <sys/types.h> //fork
        #include <unistd.h> //fork and sleep
          
        int main() 
        { 
            // Fork returns process id 
            // in parent process 
            pid_t child_pid = fork(); 
          
            // Parent process didn't use wait and finished before child
            // so the child becomes an orphan process
        
            // Parent process 
            if (child_pid > 0) {
                printf("I finished my execution before my child"); 
            }
            else // Child process 
                if (child_pid == 0) { 
                    sleep(1); //sleep for 1 second
                    printf("This printf will not be executed"); 
                } 
                else{
                    //error occurred
                }
          
            return 0; 
        }
        

        输出

        我在孩子之前完成了我的处决

        僵尸

        // A C program to demonstrate Zombie Process. 
        // Child becomes Zombie as parent is not waiting
        // when child process exits. 
        
        #include <stdio.h>  //printf
        #include <stdlib.h> //exit
        #include <sys/types.h> //fork
        #include <unistd.h> //fork and sleep
        
        int main() 
        { 
            // Fork returns process id 
            // in parent process 
            pid_t child_pid = fork(); 
         
            // Parent process didn't use wait 
            // so the child becomes a zombie process
        
            // Parent process 
            if (child_pid > 0){ 
                sleep(1); //sleep for 1 second
                printf("\nI don't wait for my child");
            }
            else // Child process 
                if(child_pid == 0){ 
                    printf("My parent doesn't wait me");
                    exit(0);
                }
                else{
                    //error occurred
                }
            
            return 0; 
        } 
        

        输出

        我的父母不等我

        我不等我的孩子

        编辑:来源和灵感来自here

        【讨论】:

          【解决方案5】:

          一个已经完成执行但在进程表中仍然有要向其父进程报告的条目的进程称为僵尸进程。 父进程不存在的进程,即在没有等待其子进程终止的情况下完成或终止的进程称为孤儿进程

          【讨论】:

            【解决方案6】:

            孤儿进程是其parent process 已完成或终止的计算机进程,尽管它(子进程)仍在运行。
            僵尸进程或失效进程是指已完成执行但在进程表中仍有一个条目的进程,因为它的父进程没有调用wait() 系统调用。

            【讨论】:

              【解决方案7】:
              1. 没有孤儿,只有使用 PID 1 的进程。

                从正在运行的进程的角度来看,它是直接启动并因此具有 PID 1 作为父进程,还是由于其原始父进程(不同于 PID 1)结束而被 PID 1 继承,都没有区别。 它的处理方式与任何其他进程一样。

              2. 每个进程在结束时都会经历某种僵尸状态,即在通过发出 SIGCHLD 宣布其结束和确认其处理(交付或无知)之间的阶段。

              当进入僵尸状态时,进程只是系统进程列表中的一个条目。

              僵尸独占使用的唯一重要资源是有效的 PID。

              【讨论】:

                【解决方案8】:

                当一个进程终止时,它的资源被操作者释放 系统。但是,它在进程表中的条目必须保留在那里,直到 parent 调用 wait(),因为进程表包含进程的退出状态。 已终止但其父进程尚未调用 wait() 的进程是 称为僵尸进程。当所有进程都转换到这个状态时 终止,但通常它们只是短暂地作为僵尸存在。一旦父母 调用wait(),僵尸进程的进程标识符及其在 进程表被释放。

                现在考虑如果父母没有调用 wait() 会发生什么,并且 而是终止,从而使其子进程成为孤儿。 Linux 和 UNIX 通过将 init 进程分配为孤立进程的新父进程来解决这种情况。周期性的init进程 调用 wait(),从而允许任何孤立进程的退出状态 收集并释放孤儿的进程标识符和进程表条目。

                来源:操作系统概念 by Abraham, Peter, Greg

                【讨论】:

                • 真的很喜欢这个简短明了的答案。
                • 所以事实上没有孤儿,因为他们被收养了。
                【解决方案9】:

                当一个子进程退出时,某个进程必须对其进行wait 才能获得其退出代码。该退出代码存储在进程表中,直到发生这种情况。阅读该退出代码的行为称为“收割”孩子。在孩子离开并被收割之间,它被称为僵尸。 (仔细想想,整个命名法有点令人毛骨悚然;我建议不要想太多。)

                僵尸只占用进程表中的空间。它们不占用内存或 CPU。但是,进程表是有限资源,过多的僵尸可以填满它,这意味着没有其他进程可以启动。除此之外,它们是令人讨厌的混乱,应该强烈避免。

                如果一个进程退出时子进程仍在运行(并且没有杀死它的子进程;比喻仍然很奇怪),那么这些子进程就是孤儿。孤儿立即被init“收养”(实际上,我认为大多数人称之为“重新养育”,但“收养”似乎更适合这个比喻)。孤儿只是一个过程。它将使用它使用的任何资源。按理说它根本不是“孤儿”,因为它有父母,但我经常听到他们这么叫。

                init 自动收割它的孩子(收养或其他)。所以如果你不清理你的孩子就退出,那么他们就不会变成僵尸(至少不会超过片刻)。

                但是长寿的僵尸是存在的。这些是什么?他们是尚未收获的现有流程的前孩子。进程可能会挂起。或者它可能写得不好,忘记收获它的孩子。或者它可能已经超载并且没有解决它。管他呢。但是由于某种原因,父进程继续存在(因此它们不是孤儿),并且它们没有被等待,因此它们在进程表中作为僵尸继续存在。

                因此,如果您看到僵尸的时间超过片刻,则意味着父进程有问题,应该采取一些措施来改进该程序。

                【讨论】:

                  猜你喜欢
                  • 1970-01-01
                  • 1970-01-01
                  • 2014-09-30
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 2010-11-12
                  相关资源
                  最近更新 更多