关于linux的僵尸进程的产生原因的分析

最近在学习linux的内核,在看完网上的一些wait4调用和do_exit调用说明后对僵尸进程的产生的缘由也有了一个大致的了解,

在此对其作个总结:

首先是do_exit()调用:

do_exit(long code)

(1) __exit_mm(tsk): //释放存储空间
(2) sem_exit();          //释放用户空间的“信号量”
(3) __exit_files(tsk); //释放已经打开的文件
(4) __exit_fs(tsk);     //释放用于表示工作目录等结构
(5) exit_sighand(tsk);//释放信号处理表
(6) exit_thread();
(7) tsk->exit_code = code;
(8) exit_notify();         //通知父进程该“退出”消息,父进程将负责回收这个进程描述符
(9) schedule();

 

当一个子进程调用exit(*)调用时,会清理掉它自身的相关内存数据

exit_notify

(1)forget_original_parent:因为当前进程要“去世”,那么首先得把它所有的子进程托付给另外一个进程。如果当前这个进程是个线程(有点混乱,确切地说当前这个task实质上表示的是一个线程),那么就托服给线程组的下一个线程。否则,就托付给init进程。
(2)current->state = TASK_ZOMBIE
(3)do_notify_parent:告知父进程其子进程结束的消息
        send_sig_info(..., tsk->p_pptr):向父进程发送信号通知其自身结束的消息
         wake_up_parent(tsk->p_pptr):唤醒父进程使之进入可调度队列(状态变为TASK_RUNNING)

 

注意:在exit_notify中会将该子进程的状态标志转成zombie,僵尸!

 

那么我们再看看父进程需要做什么:

父进程调用wait4来清理子进程的残留信息:

sys_wait4(pid_t pid,unsigned int * stat_addr, int options, struct rusage * ru)

     DECLARE_WAITQUEUE(wait, current);
     add_wait_queue(&current->wait_chldexit,&wait);
repeat:
     flag = 0;
     current->state = TASK_INTERRUPTIBLE;
     tsk = current;
    do {
        struct task_struct *p;
        for (p = tsk->p_cptr ; p ; p = p->p_osptr) {
            if (pid>0) {                                  //pid>0,说明寻找进程号等于pid的子进程
                if (p->pid != pid)
                    continue;
            } else if (!pid) {                           //pid=0,说明寻找与当前进程同一个组的子进程
                if (p->pgrp != current->pgrp)
                    continue;
            } else if (pid != -1) {                    //pid<-1,说明寻找进程组编号等于-pid的子进程
                if (p->pgrp != -pid)
                    continue;
                                                            //pid=-1,说明寻找任何一个子进程
            flag = 1;
            switch (p->state) {
            case TASK_STOPPED: ...goto end_wait4;
            case TASK_ZOMBIE: ...release_task(p); goto end_wait4; //子进程已结束,释放其描述符
            default: continue;
            }
            if (option & __WNOTHREAD) break;
            tsk = next_thread(tsk);
    }while(tsk != current) 

    if (flag) {
        ...
        schedule();       //子进程没有结束,继续睡眠,下次仍然跳到repeat处扫描子进程列表
        goto repeat;
    }
end_wait4:
    current->state = TASK_RUNNING;
    remove_wait_queue(&current->wait_chldexit,&wait);
    return retval;
}

当父进程发现子进程发现子进程的状态为zombie时会负责清理它的遗留信息,所以在编写多进程的时候父进程在处理子进程的退出务必要使用wait相关操作,负责会使得子进程的信息不干净变成僵尸进程。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值