进程关系:父子进程和僵尸进程

前言:

        在操作系统中,进程是资源分配的基本单位。进程之间存在着复杂的关系,其中最重要的就是父子进程关系和僵尸进程。

1.父子进程:

        父子进程是操作系统中最基本的进程关系。当一个进程创建另一个进程时,被创建的进程就成为父进程的子进程。子进程继承了父进程的大部分属性,如环境变量、工作目录等。可以初略的认为子进程只是父进程的拷贝。

下面我用两个简单的示例,来演示了父子进程。在这个示例中,ParentChildProcess类创建了一个子进程ChildProcess,并等待子进程结束。子进程在执行5秒钟的任务后退出。

(java)

public class ParentChildProcess {
    public static void main(String[] args) {
        System.out.println("Parent process started, PID: " + ProcessHandle.current().pid());

        ProcessBuilder processBuilder = new ProcessBuilder("java", "ChildProcess");
        try {
            Process childProcess = processBuilder.start();
            int childPid = (int) childProcess.pid();
            System.out.println("Child process started, PID: " + childPid);

            int exitCode = childProcess.waitFor();
            System.out.println("Child process exited with code: " + exitCode);
        } catch (Exception e) {
            e.printStackTrace();
        }

        System.out.println("Parent process finished.");
    }
}

class ChildProcess {
    public static void main(String[] args) {
        System.out.println("Child process started, PID: " + ProcessHandle.current().pid());
        // 模拟子进程执行一些任务
        try {
            Thread.sleep(5000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("Child process finished.");
    }
}

(c):

  1. 父进程首先打印自己的进程ID。
  2. 使用fork()函数创建子进程。
  3. 如果返回值是-1,表示创建子进程失败,打印错误信息并退出。
  4. 如果返回值是0,表示当前进程是子进程,打印子进程的进程ID,然后模拟执行5秒钟的任务,最后退出。
  5. 如果返回值大于0,表示当前进程是父进程,打印等待子进程完成的信息。
  6. 父进程使用waitpid()函数等待子进程退出,并获取子进程的退出状态。
  7. 根据退出状态,打印子进程是否正常退出。
  8. 最后,父进程打印自己已经完成。
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>

int main() {
    pid_t pid;

    printf("Parent process started, PID: %d\n", getpid());

    // 创建子进程
    pid = fork();

    if (pid == -1) {
        // 创建子进程失败
        perror("fork");
        return 1;
    } else if (pid == 0) {
        // 子进程
        printf("Child process started, PID: %d\n", getpid());

        // 模拟子进程执行一些任务
        sleep(5);

        printf("Child process finished.\n");
        return 0;
    } else {
        // 父进程
        int status;

        printf("Parent process waiting for child process to finish...\n");
        waitpid(pid, &status, 0);

        if (WIFEXITED(status)) {
            printf("Child process exited with status %d\n", WEXITSTATUS(status));
        } else {
            printf("Child process did not exit normally\n");
        }

        printf("Parent process finished.\n");
        return 0;
    }
}

         编译代码以后,会得到以下效果

2.僵尸进程产生的原因:

        当一个子进程退出时,它的父进程应该及时回收子进程的资源,如内存、CPU时间等。但是,如果父进程没有及时回收子进程的资源,则子进程会变成"僵尸进程"。
注意:僵尸进程不会占用系统资源,但它会一直存在于进程表中,直到父进程对其进行回收。

        接下里我们就直接用shell创建一个子进程然后没有父进程来对他进行回收。看一下具体的效果。在这个示例中,首先我们使用父进程创建了一个子进程,然后等待5秒钟后退出父进程。但是,子进程在父进程退出之前并没有完全执行完毕,所以现在子进程就没有对应的父进程来回收了。也就成为了僵尸进程。注意这里的僵尸进程和死循环的区别哦。

#!/bin/bash

echo "Parent process started, PID: $$"

# 创建子进程
./child_process.sh &
child_pid=$!

echo "Child process started, PID: $child_pid"

# 等待5秒钟
sleep 5

echo "Parent process finished."
#!/bin/bash

echo "Child process started, PID: $$"

# 模拟子进程执行一些任务,然后直接退出
sleep 10
exit 0

3.避免产生僵尸进程方法:

        父进程需要及时回收子进程的资源。在Java中,可以使用Process.waitFor()方法等待子进程退出,并获取退出状态码。在Shell脚本中,可以使用wait命令等待子进程退出。

4.总结:

        父子进程是操作系统中实现多任务并发处理的基础,而僵尸进程则是这一机制的潜在副作用。减少僵尸进程的发生,保障系统稳定高效运行。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值