使用代码模拟实现僵尸进程,孤儿进程的场景

本文介绍了僵尸进程和孤儿进程的概念及实例。僵尸进程是指子进程退出后,父进程未读取其退出状态而产生的特殊状态;孤儿进程则是指父进程先于子进程退出的情况。文章通过两个C语言示例程序,展示了这两种进程的具体表现形式及其处理方式。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1.僵尸进程
僵死状态是一个比较特殊的状态。当进程退出并且父进程没有读取到子进程退出的返回码时就会产生僵尸进程。
僵尸进程会以终止状态保持在进程表中,并且会一直在等待父进程读取退出状态代码。
所以,只要子进程退出,父进程还在运行,但父进程没有读取子进程状态,子进程进入僵死状态。
列举一个创建维持30秒的僵死进程例子:

#include<stdio.h>
#include<stdlib.h>
int main()
{
     pid_t id = fork();
     if(id<0){
           perror("fork");
           return 1;
         }
         else if(id>0){
              printf("parent[%d] is sleeping...\n",getpid());
              sleep(30);
         }else{
              printf("child[%d] is begin Z...\n",getpid());
              sleep(5);
              exit(EXIT_success);
         }
         return 0;
}
运行程序后

在这里插入图片描述
这个僵尸进程维持30秒之后退出。
僵尸进程危害
(1)进程的退出状态必须被维持下去,因为他要告诉关心他的进程(父进程),你交给我的任务,我完成的怎么样,可父进程如果一直不读取,那子进程就一直处于僵死状态。
(2)维护退出状态本身就是要用数据维护,也属于进程基本信息,所以保存在task_struct(pcb)中,换句话说,z状态一直不退出,pcb一直都要维护。
(3)会造成内存资源的浪费(因为数据结构对象本身就要占用内存,想想c中定义一个结构体变量,是要在内存的某个位置进行开辟空间)
(4)会造成内存泄漏
2.孤儿进程
父进程先退出,子进程就被成为孤儿进程

#include<stdio.h>
#include<unistd.h>
#include<stdlib.h>
int main(){
    pid_t id=fork();
    if(id<0){
        perror("fork");
        return 1;
    }
    else if(id==0){
        printf("i am child,pid:%d\n",getpid());
        sleep(10);
    }else{
            printf("i am parent,pid:%d\n",getpid());
            sleep(3);
            exit(0);
            }
            return 0;
 }

运行程序后
在这里插入图片描述
这个孤儿进程在3秒后被回收。

### Python 子进程未调用 `exit()` 且父进程结束后,`systemd` 是否会负责回收 在 Linux 系统中,当一个子进程的父进程已经结束时,该子进程不会成为僵尸进程[^1]。这是因为系统会在父进程结束时扫描所有运行中的进程,并将任何属于已结束父进程的子进程交由 `init` 进程(即 PID 为 1 的进程)接管[^4]。`init` 进程会自动调用 `wait()` 来清理这些子进程的状态,从而防止它们变为僵尸进程。 然而,在现代 Linux 系统中,许多服务是由 `systemd` 管理的。在这种情况下,`systemd` 实际上充当了 `init` 进程的角色。这意味着即使父进程结束了,子进程也会被 `systemd` 接管并处理其退出状态。因此,只要子进程最终能够正常退出,无论是否显式调用了 `exit()`,`systemd` 都能确保其资源得到释放。 需要注意的是,如果子进程并未主动调用 `exit()` 并进入无限循环或其他无法终止的状态,则它并不会真正退出。这种情况下,虽然 `systemd` 可以接管该进程,但由于进程本身并未完成执行周期,也不会形成僵尸进程[^3]。相反,这可能是一个长期运行的任务或错误行为,需进一步排查解决。 以下是基于上述理论的一个简单验证代码: ```python from multiprocessing import Process import os import time def infinite_task(): while True: pass # 模拟进程不调用 exit() if __name__ == "__main__": print(f"Parent process ID: {os.getpid()}") child_process = Process(target=infinite_task) child_process.start() # 主程序立即退出模拟进程崩溃场景 ``` 在此示例中,尽管父进程提前结束,但如果子进程陷入死循环而不调用 `exit()`,则它既不是僵尸也不是孤儿进程,而是持续占用系统资源直到手动干预为止[^2]。 #### 总结 对于 Python 编写的多进程应用程序而言,一旦父进程意外终止,而子进程未能及时退出的情况下,`systemd` 将承担起原本属于 `init` 的职责去监控和管理那些遗留下来的子进程。不过前提是这些子进程确实完成了自身的生命周期并且允许被安全销毁;否则即便有高级别的管理系统支持也无法强制关闭某些顽固型任务。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值