linux中的僵尸进程

原创 2016年11月20日 21:39:46

如果一个进程已经退出或者被杀死,但是它的父进程尚未执行wait操作,那么该进程进入僵尸(zombie)状态。这种进程不再参与调度,它的内存也会被释放,但系统不会把它从进程表中删除(top 命令中显示状态为Z)。僵尸在进程等待父进程回收它的退出状态。

原文:小宇的博客

这篇文章会告诉你:
1. 僵尸进程产生原理。
2. 如何产生僵尸进程。
3. 如何回收僵尸进程。

产生僵尸进程

根据僵尸进程的定义,我们不难用c语言来产生一个僵尸进程

#include<unistd.h>
#include<stdio.h>
#include<stdlib.h>
#include<string.h>

#define MB 1024*1024

int main()
{

    int pid;

    printf("new process PID=%d\n", getpid());
    pid = fork();
    if(pid==0)
    {   
        /* child */
        printf("new process PID=%d\n", getpid());
        char * p = malloc(512*MB);
        memset(p,0,512*MB);
        exit(0);
    }   
    else
    {   
        /* parent */
        sleep(60);
    }   
}      

编译并执行该程序,然后再看该程序进程的状态:

$ ./main 
new process PID=25810
new process PID=25811

$ ps aux | grep main
yshen    25810  0.0  0.0   4200   620 pts/31   S+   14:30   0:00 ./main
yshen    25811  0.0  0.0      0     0 pts/31   Z+   14:30   0:00 [main] <defunct>

可以看到,主进程的状态为S+即休眠状态,子进程的状态为Z+即僵尸状态。此时僵尸进程等待父进程读取其退出状态。在该程序中等待父进程退出之后,子进程也将退出(因为子进程的状态在父进程退出之后已经没什么用了)。

用top命令来查看内存占用情况,可以看到实僵尸进程的内存占用等于0.

$ top
  PID USER      PR  NI    VIRT    RES    SHR S  %CPU %MEM     TIME+ COMMAND 
25810 yshen     20   0    4200    792    712 S   0.0  0.0   0:00.00 main
25811 yshen     20   0       0      0      0 Z   0.0  0.0   0:00.67 main

处理僵尸进程

根据以上分析,我们不难得出僵尸进程退出的2种情况:
1. 父进程用wait/waitpid来获取子进程的状态。
2. 父进程退出。

子进程退出,也会给父进程发送SIGCHLD信号来通知。在实际编码中,一般应SIGCHLD信号进行处理。(如:重新fork拉起子进程或进行垃圾回收,记录日志等等)。如下例子我们注册SIGCHLD信号处理函数,等待子进程退出时由父进程调用wait来获取其退出状态。

#include<unistd.h>
#include<stdio.h>
#include<stdlib.h>
#include<signal.h>

void handler(int code)
{
    int status;
    pid_t pid = wait(&status);
    printf("parent get SIGCHLD, child %d returned %d\n",
                                    pid, WEXITSTATUS(status));
    sleep(60); /* 加这行是因为父进程收到SIGCHLD信号打断了原来的sleep,如果不加这个父进程就会马上退出 */
}

int main()
{

    int pid;
    signal(SIGCHLD,handler);

    printf("new process PID=%d\n", getpid());
    pid = fork();

    if(pid==0)
    {
        /* child */
        printf("new process PID=%d\n", getpid());
        exit(123);
    }
    /* parent */
    sleep(60);
    exit(0);
}

编译并执行。

$ ./main 
new process PID=26559
new process PID=26560
parent get SIGCHLD, child 26560 returned 123

$ ps aux | grep main
yshen    26604  0.0  0.0   4200   624 pts/31   S+   15:07   0:00 ./main

可以看到,已经没有僵尸进程了。

版权声明:本文为博主原创文章,未经博主允许不得转载。

相关文章推荐

linux中的僵尸进程

  • 2012年05月21日 11:26
  • 6KB
  • 下载

Linux避免僵尸进程

  • 2013年04月28日 13:49
  • 177KB
  • 下载

linux_wait()与僵尸进程

在UNIX 系统中,一个进程结束了,但是他的父进程没有等待(调用wait / waitpid)他, 那么他将变成一个僵尸进程. 但是如果该进程的父进程已经先结束了,那么该进程就不会变成僵尸进程, 因为...

Linux scp远程文件/目录传输 用ps和grep命令寻找僵尸进程

Linux scp远程文件/目录传输 现在越来越多的朋友有租用vps其中相当一部分都是基于linux的,那么在日常使用中使用最多的估计就是上传web文件了。 因此scp命令的使用概率也越来越高,大...

Linux安全攻略—僵尸进程

Linux安全攻略—僵尸进程 [ tempzjm 发表于 2005-10-23 16:14:00 ]  Linux安全攻略—僵尸进程  -----------------------------...

Linux的僵尸进程及其解决方法

Linux的僵尸进程及其解决方法 1. 产生原因:      在UNIX 系统中,一个进程结束了,但是他的父进程没有等待(调用wait / waitpid)他,那么他将变成一个...

Linux 僵尸进程产生及如何避免

在fork()/execve()过程中,假设子进程结束时父进程仍存在,而父进程fork()之前既没安装SIGCHLD信号处理函数调用waitpid()等待子进程结 束,又没有显式忽略该信号,则子进程成...

Linux的僵尸进程

在Unix系统管理中,当用ps命令观察进程的执行状态时,经常看到某些进程的状态栏为defunct,这就是所谓的“僵尸”进程。“僵尸”进程是一个早已死亡的进程,但在进程表(processs table)...

Linux的僵尸进程解决攻略

Linux主机引起强悍的安全性和稳定而收到各方站长的喜爱,但是Linux有一定的局限性就是操作复杂,需要使用者掌握一定的基础只是,如果不懂得其中的运行原理,麻烦还是不少的,下面我们就僵尸进程这个问题来...
  • heybob
  • heybob
  • 2013年09月11日 19:49
  • 635

网络编程(32)—— linux中销毁僵尸进程的四种方法

一、wait函数 函数原型: pid_t wait(int *status); 描述: wait可以回收任意一个僵尸进程,只要系统中存在僵尸进程,调用一次wait,就会回收一个僵尸进程。 参数说明...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:linux中的僵尸进程
举报原因:
原因补充:

(最多只允许输入30个字)