僵尸进程:子进程退出后,父进程还没有回收子进程的资源,那么这个子进程就处于僵尸状态。
Q1:“资源”是些什么?
Q2:父进程如何回收子进程的资源?

内核为每个终止子进程保存了一定量的信息,所以当终止进程的父进程调用wait或waitpid时,可以得到这些信息。
这些信息至少包括进程ID,该进程的终止状态,以及该进程使用的CPU时间总量.
内核可以释放终止进程所使用的所有存储区,关闭其所有打开的文件.

如果编写一个长期运行的程序,他调用fork产生了很多子进程,那么除非父进程等待来取得子进程的终止状态,否则这些子进程终止后就会变成僵尸进程。

避免僵尸进程的方法
方法1:调用两次fork可以避免僵尸进程的产生。

 #include <stdio.h>
#include <stdlib.h> int main(void)
{
pid_t pid; if ((pid = fork()) < )
{
printf("fork error\n");
exit(-);
}
else if (==pid) /*first child*/
{
printf("1first child pid=%d\n", getpid());
if ((pid = fork())<)
{
printf("fork error\n");
exit(-);
}
else if (pid > ) /*parent from second fork == first child*/
{
printf("2first child pid=%d, first child exit\n", getpid());
exit();//first child exit
} printf("second child pid=%d\n", getpid());
/*I am the second child, my parent become init as soon as my real parent calls exit() in the statement above
* Here's where we'd continue executing, knowing that when we're done, init will reap out status*/
sleep();
printf("second child, parent pid = %d, second child exit\n", getppid());
exit();
} printf("pararent pid=%d\n", getpid());
if (waitpid(pid, NULL, ) != pid) /*wait for first child*/
{
printf("waitpid error\n");
exit(-);
}
printf("parent exit"); /*I am the parent(the original process); I continue executing, knowing that I'm not the parent of the second child*/ exit();
}

方法2:当SIGCHLD的处理方式是系统默认时,父进程调用了wait()以避免僵尸进程的产生,此方法中,父进程阻塞。

 #include <stdio.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <errno.h>
#include <signal.h> void print_exit(int status)
{
if (WIFEXITED(status))
printf("normal termination, exit status = %d\n", WEXITSTATUS(status));
else if (WIFSIGNALED(status))
printf("abnormal termination, signal number = %d%s\n", WTERMSIG(status),
#ifdef WCOREDUMP
WCOREDUMP(status) ? ("core file generated") : (""));
#else
"");
#endif
else if (WIFSTOPPED(status))
printf("child stopped, signal number=%d\n", WSTOPSIG(status));
} void sig_child(int signo)
{
int status;
int ret;
ret = wait(&status);
printf("pid:%d, res:%d, status=%d, %s\n", getpid(), ret, status, strerror(errno));
print_exit(status);
} void sig_usr(int signo)
{
if (signo == SIGUSR1)
printf("received SIGUSR1\n");
else if (signo == SIGUSR2)
printf("received SIGUSR2\n");
else
printf("received signal %d\n", signo);
} int main(int argc, char** argv)
{
pid_t pid;
int status;
int ret; if ((pid=fork()) < )
{
printf("fork error\n");
return -;
}
else if (pid == )
{
printf("child exit\n");
return ;
}
else
{
//printf("parent sleep(100)\n");
//sleep(100);
ret = wait(&status);
print_exit(status);
printf("parent exit\n");
} exit();
}

方法3:当SIGCHLD的处理方式是捕获时,在其信号处理程序中调用wait()函数以避免僵尸进程的产生,此方法中,父进程不阻塞。

 #include <stdio.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <errno.h>
#include <signal.h> void print_exit(int status)
{
if (WIFEXITED(status))
printf("normal termination, exit status = %d\n", WEXITSTATUS(status));
else if (WIFSIGNALED(status))
printf("abnormal termination, signal number = %d%s\n", WTERMSIG(status),
#ifdef WCOREDUMP
WCOREDUMP(status) ? ("core file generated") : (""));
#else
"");
#endif
else if (WIFSTOPPED(status))
printf("child stopped, signal number=%d\n", WSTOPSIG(status));
} void sig_child(int signo)
{
int status;
int ret;
ret = wait(&status);
printf("pid:%d, res:%d, status=%d, %s\n", getpid(), ret, status, strerror(errno));
print_exit(status);
} void sig_usr(int signo)
{
if (signo == SIGUSR1)
printf("received SIGUSR1\n");
else if (signo == SIGUSR2)
printf("received SIGUSR2\n");
else
printf("received signal %d\n", signo);
} int main(int argc, char** argv)
{
pid_t pid;
struct sigaction act, oact;
int status;
int ret; act.sa_handler = sig_child;
sigemptyset(&act.sa_mask);
//act.sa_flags = 0|SA_NOCLDWAIT;
sigaction(SIGCHLD, &act, &oact); if ((pid=fork()) < )
{
printf("fork error\n");
return -;
}
else if (pid == )
{
printf("child exit\n");
return ;
}
else
{
printf("parent sleep(100)\n");
sleep();
printf("parent exit\n");
} exit();
}

从打印中可以看出,信号处理程序由父进程调用
方法4:设置SIGCHLD为SA_NOCLDWAIT,当子进程终止时,不创建僵尸进程。父进程中不需调用wait。

 #include <stdio.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <errno.h>
#include <signal.h> void print_exit(int status)
{
if (WIFEXITED(status))
printf("normal termination, exit status = %d\n", WEXITSTATUS(status));
else if (WIFSIGNALED(status))
printf("abnormal termination, signal number = %d%s\n", WTERMSIG(status),
#ifdef WCOREDUMP
WCOREDUMP(status) ? ("core file generated") : (""));
#else
"");
#endif
else if (WIFSTOPPED(status))
printf("child stopped, signal number=%d\n", WSTOPSIG(status));
} void sig_usr(int signo)
{
if (signo == SIGUSR1)
printf("received SIGUSR1\n");
else if (signo == SIGUSR2)
printf("received SIGUSR2\n");
else
printf("received signal %d\n", signo);
} int main(int argc, char** argv)
{
pid_t pid;
struct sigaction act, oact;
int status;
int ret; act.sa_handler = sig_usr;
sigemptyset(&act.sa_mask);
act.sa_flags = |SA_NOCLDWAIT;
sigaction(SIGCHLD, &act, &oact); if ((pid=fork()) < )
{
printf("fork error\n");
return -;
}
else if (pid == )
{
printf("child exit\n");
return ;
}
else
{
printf("parent sleep(100)\n");
sleep();
//ret = wait(&status);
//print_exit(status);
printf("parent exit\n");
} exit();
}

zombie process的更多相关文章

  1. linux zombie process相关学习

    1. zombie process是什么? zombie process是那些在系统中已经死掉的process, 通过ps -A | grep defunct可以查看系统中有多少zombie proc ...

  2. 僵尸进程(zombie process)

    僵尸进程(zombie process) http://blog.csdn.net/crfoxzl/article/details/2124718 杀死Linux中的defunct进程(僵尸进程)的方 ...

  3. linux 杀掉僵尸进程 (zombie process, defunct)

    本文说明为什么会出现僵尸进程 (zombie process, defunct),以及如何杀掉僵尸进程 1. 为什么有僵尸进程 僵尸进程出现在父进程没有回收子进程的 PCB 的时候,这个时候子进程已经 ...

  4. 僵尸进程(zombie process)

    首先了解一下linux中进程的5大状态: R Running or runnable (on run queue)S Interruptible sleep (waiting for an event ...

  5. 避免产生僵尸进程的N种方法(zombie process)

    http://blog.csdn.net/duyiwuer2009/article/details/7964795 认识僵尸进程 1.如果父进程先退出 子进程自动被 init 进程收养,不会产生僵尸进 ...

  6. Linux Process VS Thread VS LWP

    Process program program==code+data; 一个进程可以对应多个程序,一个程序也可以变成多个进程.程序可以作为一种软件资源长期保存,以文件的形式存放在硬盘 process: ...

  7. Linux进程状态 ( Linux Process State Codes)

    进程状态代码及说明: STATE代码 说明 D 不可中断的睡眠. 通常是处于I/O之中. R 运行中/可运行. 正处于运行队列中. S 可中断的睡眠. 等待某事件发生. T 已停止. 可能是因为she ...

  8. Linux编程学习笔记 -- Process

    进程是一个程序的运行.   在一个程序中执行另一个执程序的方法有两种: 1)system 在shell中执行程序 2)fork + exec 复制一个进程,在进程中用新的程序替换原有的程序   for ...

  9. process thread Fiber(linux)

    http://blog.chinaunix.net/uid-21084809-id-2215376.html Processes, kernel threads, user threads, and ...

随机推荐

  1. 「Baltic2015」Network

    题目描述 原文 The government of Byteland has decided that it is time to connect their little country to th ...

  2. [Contest20180116]随机游走

    题意:给一棵树,多次询问$a$到$b$期望步数,每一步都是随机的 对期望DP了解更深入了一些 先预处理$up_x$表示从$x$走到$fa_x$的期望步数 可以直接往上走,也可以先去儿子再回来,设$x$ ...

  3. 【计算几何】bzoj2338 [HNOI2011]数矩形

    对于两条线段,若其中点重合,且长度相等,那么它们一定是某个矩形的对角线. N*N地处理出所有线段,排序,对每一部分中点重合.长度相等的线段进行暴力枚举,更新答案. 用 long double 注意EP ...

  4. 显示ACSII码字符表 Exercise05_15

    /** * @author 冰樱梦 * 时间:2018年下半年 * 题目:显示ACSII码字符表 * */ public class Exercise05_15 { public static voi ...

  5. Asp.Net MVC part6 WebAPI

    两种web服务SOAP风格:基于方法,产品是WebServiceREST风格:基于资源,产品是WebAPI可以返回json.xml类型的数据对于数据的增.删.改.查,提供相对的资源操作,按照请求的类型 ...

  6. 【tomcat】FileNotFoundException: C:\Program Files\Java\apache-tomcat-8.5.11-geneshop3\webapps\ROOT\index.html (拒绝访问。)

    新装系统后,tomcat启动起来 提示如下错误: Caused by: java.io.FileNotFoundException: C:\Program Files\Java\apache-tomc ...

  7. 【Git】GitHub for Windows使用(2) 分支

    目录 1.回看客户端相关功能 2.新建一个分支 3.在新分支上修改文件 4.上传新建分支上的修改,并合并分支 5.删除分支 1.回看客户端相关功能 看看设置中的以下内容 2.新建一个分支 3.在新分支 ...

  8. 用iptables做NAT代理,使内网机器上外网

    现状:服务器A只有一个内网IP,不能上外网,内网IP与服务器B内网相通:服务器B有一个内网IP和公网IP.想实现服务器A也能上外网. 1 2 3 4 服务器A:内网网卡:eth0 内网IP:192.1 ...

  9. 蒙皮 skin

    http://help.autodesk.com/view/MAYAUL/2016/CHS/?guid=GUID-EFE68C08-9ADA-4355-8203-5D1D109DCC82 skin:顶 ...

  10. Linux程序编译链接动态库版本号的问题

    不同版本号的动态库可能会不兼容,假设程序在编译时指定动态库是某个低版本号.执行是用的一个高版本号,可能会导致无法执行. Linux上对动态库的命名採用libxxx.so.a.b.c的格式.当中a代表大 ...