僵尸线程

简介: 来源:http://www.cnblogs.com/dongzhiquan/archive/2012/07/12/2588906.html   在每个进程退出的时候,内核释放该进程所有的资源,包括打开的文件,占用的内存等.但是仍然为其保留一定的信息(包括进程号the process ID,退出状态the termination status of the process,运行时间the amount of CPU time taken by the process等),直到父进程通过wait / waitpid来取时才释放,此时该进程便成为僵尸进程。

来源:http://www.cnblogs.com/dongzhiquan/archive/2012/07/12/2588906.html

 

在每个进程退出的时候,内核释放该进程所有的资源,包括打开的文件,占用的内存等.但是仍然为其保留一定的信息(包括进程号the process ID,退出状态the termination status of the process,运行时间the amount of CPU time taken by the process等),直到父进程通过wait / waitpid来取时才释放,此时该进程便成为僵尸进程。


1.什么是僵尸进程?
    UNIX 系统中,一个进程结束了,但是他的父进程没有等待(调用wait / waitpid)他,而父进程还没有结束,那么他将变成一个僵尸进程.
    如果该进程的父进程已经先结束了,那么该进程就不会变成僵尸进程,因为每个进程结束的时候,系统都会扫描当前系统中所运行的所有进程,看有没有哪个进程是 刚刚结束的这个进程的子进程,如果是的话,就由Init来接管他,成为他的父进程,从而保证每个进程都会有一个父进程.而Init进程会自动wait其子 进程,因此被Init接管的所有进程都不会变成僵尸进程.

2.子进程结束后为什么要进入僵尸状态?
    因为父进程可能要取得子进程的退出状态等信息。

3.僵尸状态是每个子进程比经过的状态吗?
    是的。任何一个子进程(init除外)在exit()之后,并非马上就消失掉,而是留下一个称为僵尸进程(Zombie)的数据结构,等待父进程处理。这 是每个 子进程在结束时都要经过的阶段。如果子进程在exit()之后,父进程没有来得及处理,这时用ps命令就能看到子进程的状态是“Z”。如果父进程能及时 处理,可能用ps命令就来不及看到子进程的僵尸状态,但这并不等于子进程不经过僵尸状态。
    如果父进程在子进程结束之前退出,则子进程将由init接管。init将会以父进程的身份对僵尸状态的子进程进行处理。

4.如何查看僵尸进程:
    $ ps -el
    其中,有标记为Z的进程就是僵尸进程
    S代表休眠状态;D代表不可中断的休眠状态;R代表运行状态;Z代表僵死状态;T代表停止或跟踪状态

5.僵尸进程的避免
    1、父进程通过wait和waitpid等函数等待子进程结束,这会导致父进程挂起
    2. 如果父进程很忙,那么可以用signal函数为SIGCHLD安装handler,因为子进程结束后,父进程会收到该信号,可以在handler中调用wait回收
    3. 如果父进程不关心子进程什么时候结束,那么可以用signal(SIGCHLD, SIG_IGN)通知内核,自己对子进程的结束不感兴趣,那么子进程结束后,内核会回收,并不再给父进程发送信号
    4. 还有一些技巧,就是fork两次,父进程fork一个子进程,然后继续工作,子进程fork一个孙进程后退出,那么孙进程被init接管,孙进程结束后,init会回收。不过子进程的回收还要自己做。

复制代码
#include "apue.h"
#include <sys/wait.h>

int main(void)
{
    pid_t pid;
    if ((pid = fork()) < 0)
    {
        err_sys("fork error");
    } 
    else if (pid == 0)
    { 
        /**//* first child */
        if ((pid = fork()) < 0)
            err_sys("fork error");
        else if (pid > 0)
            exit(0); 
        /**//* parent from second fork == first child */
        /**//*
        * We're the second child; our parent becomes init as soon
        * as our real parent calls exit() in the statement above.
        * Here's where we'd continue executing, knowing that when
        * we're done, init will reap our status.
        */
        sleep(2);
        printf("second child, parent pid = %d ", getppid());
        exit(0);
    }

    if (waitpid(pid, NULL, 0) != pid) /**//* wait for first child */
    err_sys("waitpid error");

    /**//*
    * We're the parent (the original process); we continue executing,
    * knowing that we're not the parent of the second child.
    */
    exit(0);
}
复制代码

img_e00999465d1c2c1b02df587a3ec9c13d.jpg
微信公众号: 猿人谷
如果您认为阅读这篇博客让您有些收获,不妨点击一下右下角的【推荐】
如果您希望与我交流互动,欢迎关注微信公众号
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接。

目录
相关文章
|
6月前
|
Java Unix 调度
终于把进程和线程学会了
终于把进程和线程学会了
58 0
|
5月前
|
存储 网络协议 算法
【进程与线程】最好懂的讲解
【进程与线程】最好懂的讲解
65 1
|
3月前
|
存储 Java 编译器
进程和线程
进程和线程
111 25
让“父进程”可以有自己的工作,不需要因为为了“子进程”回收资源而堵塞。但也要满足“子进程”退出后的资源能被立马回收。(不能使用任何的进程通信机制 比如:信号等)
让“父进程”可以有自己的工作,不需要因为为了“子进程”回收资源而堵塞。但也要满足“子进程”退出后的资源能被立马回收。(不能使用任何的进程通信机制 比如:信号等)
|
6月前
|
存储 Linux
【linux进程控制(二)】进程等待--父进程是如何等待子进程死亡的?
【linux进程控制(二)】进程等待--父进程是如何等待子进程死亡的?
|
6月前
获取线程号和杀不死的NSThread线程
获取线程号和杀不死的NSThread线程
34 0
|
6月前
|
Java 调度 Windows
进程与线程应用
进程与线程应用
26 2
|
消息中间件 调度
线程和进程
线程和进程
33 0
|
存储 C语言 C++
进程与线程
在我们刚开始学C语言程序设计的时候,都是单线程的,实际上我们用的电脑都是多线程的。这里说的多线程包含了并行和并发。
|
消息中间件 Java 调度
什么是线程,进程?
什么是线程,进程?
139 0