C 僵尸进程与孤立进程

C 僵尸进程与孤立进程,c,unix,fork,zombie-process,C,Unix,Fork,Zombie Process,当父进程在子进程死亡后不使用等待系统调用来读取其退出状态时,就会创建一个僵尸,当原始父进程在子进程之前终止时,孤立子进程由init回收 在内存管理和进程表方面,这些进程是如何处理的,特别是在UNIX中 当僵尸或孤儿的创建可能对更大的应用程序或系统有害时,有什么例子或极端情况 除了使用PID 1的进程之外,没有孤立项 从正在运行的进程的角度来看,它是直接启动的,因此将PID 1作为父进程,还是由PID 1继承,没有区别,因为它的原始父进程(与PID 1不同)已结束。 它的处理方式与任何其他流程一样

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

在内存管理和进程表方面,这些进程是如何处理的,特别是在UNIX中

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

  • 除了使用PID 1的进程之外,没有孤立项

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

  • 每个进程在结束时都会经历某种僵尸状态,即通过发出
    SIGCHLD
    来宣布其结束和确认其处理(传递或忽略)之间的阶段

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


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

    当子进程退出时,某些进程必须等待它以获取退出代码。该退出代码存储在进程表中,直到发生这种情况。读取退出代码的行为称为“收获”孩子。在孩子离开并被收割的这段时间里,它被称为僵尸。(仔细想想,整个命名法有点可怕;我建议不要想太多。)

    僵尸只占用进程表中的空间。它们不占用内存或CPU。然而,进程表是一个有限的资源,过多的僵尸可以填充它,这意味着没有其他进程可以启动。除此之外,它们是令人烦恼的杂乱,应该极力避免

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

    init
    自动获取其子项(收养或其他)。所以,如果你不清理你的孩子就离开,那么他们就不会变成僵尸(至少不会超过一刻)

    但长寿的僵尸依然存在。它们是什么?他们以前是一个没有收获的现有过程的孩子。该进程可能被挂起。或者它可能写得很糟糕,忘记了收获它的孩子。或者它超载了,还没来得及处理。或者别的什么。但由于某些原因,父进程仍然存在(因此它们不是孤立的),并且它们没有被等待,因此它们在进程表中作为僵尸存在


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

    当进程终止时,其资源将由操作系统释放 系统。但是,它在流程表中的条目必须保留在那里,直到 父进程调用wait(),因为进程表包含进程的退出状态。 已终止但其父进程尚未调用wait()的进程是 被称为僵尸进程。所有进程在运行时都会转换到此状态 终止,但通常它们只是短暂地作为僵尸存在。曾经的父母 调用wait(),僵尸进程的进程标识符及其在 工艺表已发布

    现在考虑如果一个父进程没有调用WAITE(),将会发生什么? 而是终止,从而将其子进程保留为孤立进程。Linux和 UNIX通过将init进程指定为孤立进程的新父进程来解决此方案。init进程将定期运行 调用wait(),从而允许更改任何孤立进程的退出状态 收集并释放孤立进程的进程标识符和进程表条目


    来源:Abraham,Peter,Greg的操作系统概念孤立进程是一个计算机进程,其
    父进程
    已完成或终止,但它(子进程)仍保持自身运行。

    僵尸进程或失效进程是一个已完成执行但在进程表中仍有一个条目的进程,因为其父进程未调用
    wait()
    系统调用。

    已完成执行但流程表中仍有要向其父流程报告的条目的流程称为僵尸流程。 父进程不存在的进程(即完成或终止而不等待其子进程终止)称为孤立进程- 父进程退出,初始化进程成为子进程的父进程。 无论何时终止子进程,操作系统都会删除进程表

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

    在linux ubuntu>>ps-eo pid、ppid、status、cmd中查看此命令


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

    我想添加两个代码片段,分别介绍一个孤立进程和一个僵尸进程。但首先,我将发布这些过程的定义,如Silberschatz、Galvin和Gagn在《操作系统概念》一书中所述:

    若并没有父级等待(并没有调用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; 
    }