Linux的“孤儿进程”的“父进程”

本文详细介绍了如何在Linux环境下通过编程产生进程关系并观察进程间的关系,包括如何制造孤儿进程及其对父进程的影响。通过实例代码,演示了如何使用fork()等基本函数创建多个进程,以及如何通过sleep()函数使某些进程成为孤儿进程,进而被init进程收养。

Linux的“孤儿进程”的“父进程”

  • 产生进程关系,观察进程间关系
  • 制造孤儿进程,观察其父进程

准备

- Linux环境
- 进程的创建的基本函数的使用(fork()等等)

1.产生进程关系,观察进程间关系


a.产生关系进程代码(process.c)
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>

int main(){
    int pid1, pid2, pid3, pid4, pid5;

    printf("1号进程开始\n");
    //得到第一个进程的pid
    pid1 = getpid();
    printf("PID1 = %d\n", pid1);

    //创建第二个进程
    pid2 = fork();
    if (pid2 == 0)
    {

        printf("2号进程开始\n");
        printf("PID 2= %d, Parent PID = %d\n", getpid(), getppid());
        printf("2号进程结束\n");

        //exit退出
        exit(0);
    }


        //创建第三个进程
        pid3 = fork();
        if (pid3 == 0)
        {
            printf("3号进程开始\n");
            printf("PID 3= %d, Parent PID = %d\n", getpid(), getppid());

        //在3号进程里面 创建第4个进程
        pid4 = fork();
        if (pid4 == 0)
        {
            printf("4号进程开始\n");
            printf("PID 4= %d, Parent PID = %d\n", getpid(), getppid());

            //sleep 3 second 
            //sleep(3);
            printf("4号进程结束\n");
            exit(0);
        }

            //在3号进程里面,创建第5个进程
        pid5 = fork();
        if (pid5 == 0)
        {

            printf("5号进程开始\n");
            printf("PID 5= %d, Parent PID = %d\n", getpid(), getppid());

            printf("5号进程结束\n");
            exit(0);
        }


        //等待子进程的结束  便于观察pid之间的关系
        sleep(3);
        printf("3号进程结束\n");
        exit(0);
    }


    //等待子线程的结束 
    sleep(5);
    printf("1号进程结束\n");
    return 0;
}


b. 编译运行

编译(注意这里用到了pthread库,所以编译的时候要加上-lpthread )

 $ gcc -o process.out process.c -lpthread 


c.运行
 $ ./process.out


d.运行结果
  • 这里写图片描述

e.分析结果
  • 这里写图片描述



2. 制造孤儿进程,观察其父进程


a.制造孤儿进程代码(processes.c)
// 主函数
int main(){

    int pid1, pid2, pid3, pid4, pid5;

    printf("1号进程开始\n");
    //得到第一个进程的pid
    pid1 = getpid();
    printf("PID1 = %d\n", pid1);

    //创建第二个进程
    pid2 = fork();
    if (pid2 == 0)
    {

        printf("2号进程开始\n");
        printf("PID2 = %d, Parent PID = %d\n", getpid(), getppid());
        printf("2号进程结束\n");

        //exit退出
        exit(0);
    }

    //创建第三个进程
    pid3 = fork();
    if (pid3 == 0)
    {
        printf("3号进程开始\n");
        printf("PID 3= %d, Parent PID = %d\n", getpid(), getppid());

        //在3号进程里面 创建第4个进程
        pid4 = fork();
        if (pid4 == 0)
        {
            printf("4号进程开始\n");
            printf("PID 4= %d, Parent PID = %d\n", getpid(), getppid());

            //sleep 3 second  等待3号进程结束,自己变成孤儿进程
            sleep(3);
            printf("4号进程结束\n");
            exit(0);
        }

        //在3号进程里面,创建第5个进程
        pid5 = fork();
        if (pid5 == 0)
        {
            printf("PID 5= %d, Parent PID = %d\n", getpid(), getppid());
            printf("5号进程开始\n");

            //sleep 3 second  等待3号进程结束,自己变成孤儿进程
            sleep(3);
            printf("5号进程结束\n");
            exit(0);
        }
        //等待子进程的结束  便于观察pid之间的关系
        printf("3号进程结束\n");                
        exit(0);
    }


    //等待子线程的结束 
    printf("1号进程结束\n");
    return 0;
}


b.编译
$ gcc -o process.out processes.c -lpthread


c.运行
$ ./process.out


d.运行结果
  • 这里写图片描述


d.运行结果分析
   其实进程间关系还是和上面程序一样的(进程1创建了进程2和进程3两个进程,然后进程3又创建了进程4和进程5),但是区别在与,进程4和进程5创建出来后,由于sleep的作用,寿命比其父进程(进程3)长,所以当进程3结束之后,进程4和进程5就变成了孤儿进程;
   在Linux系统中,孤儿进程将被init进程(进程号为1)所收养,并由init进程对它们完成状态收集工作。所以我们看到的结果就是上面的结果。
### 孤儿进程与僵尸进程的概念 #### 孤儿进程父进程退出后,子进程会失去其原本的父进程。此时,操作系统会将这些子进程交由 `init` 进程(PID通常为1)接管[^3]。这种情况下,子进程被称为孤儿进程。尽管失去了原始父进程的支持,但孤儿进程仍然可以正常运行并完成任务。 #### 僵尸进程 僵尸进程是指那些已经完成了执行的任务,但是它们的退出状态尚未被父进程通过 `wait()` 或者 `waitpid()` 函数收集的情况下的进程[^1]。虽然该进程本身不再占用CPU时间或其他资源,但由于它的条目依然存在于系统的进程表中,因此会造成一定的资源浪费。 --- ### 处理方法 #### 对于孤儿进程 由于孤儿进程会被重新分配给 `init` 进程管理,在大多数现代 Linux 系统上无需特别干预即可得到妥善处理。Init 进程会定期检查是否有新的孤儿进程加入,并负责清理这些进程的相关资源。 #### 针对僵尸进程 要消除僵尸进程,则需要确保父进程能够及时调用 `wait()` 或类似的函数来获取子进程终止后的返回码信息。如果无法修改源代码或者调试现有程序存在困难时,可以通过发送信号强制杀死父进程的方式间接解决问题——一旦原生父进程消失,原先关联的所有子进程都会成为新任 init 进程的孩子们;而后者总是勤勉地履行职责,不会留下任何未决事务。 以下是演示如何创建以及清除僵尸进程的一个简单例子: ```c #include <stdio.h> #include <stdlib.h> #include <unistd.h> int main(){ pid_t child_pid; printf("Parent process ID: %d\n", getpid()); if ((child_pid = fork()) == 0){ // Child Process Code Block sleep(2); // Simulate some work done by the child. _exit(42); }else{ /* Parent does not call wait(), leaving zombie behind */ while (1){sleep(60);} } } ``` 上述 C 程序展示了如果不适当地忽略掉等待操作的话就可能形成僵尸现象的过程。实际应用开发过程中应避免此类情况发生。 --- ###
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值