孤儿进程和僵尸进程

孤儿进程和僵尸进程

一、定义:什么是孤儿进程和僵尸进程

僵尸进程:一个子进程在其父进程还没有调用wait()或waitpid()的情况下退出。这个子进程就是僵尸进程。

孤儿进程:一个父进程退出,而它的一个或多个子进程还在运行,那么那些子进程将成为孤儿进程。孤儿进程将被init进程(进程号为1)所收养,并由init进程对它们完成状态收集工作。

僵尸进程将会导致资源浪费,而孤儿则不会。

子进程持续10秒钟的僵尸状态(EXIT_ZOMBIE)
------------------------------------------------------
#include 
#include 
#include 
#include

main()
{
pid_t pid;
pid = fork();
if(pid < 0)
printf("error occurred!/n");
else if(pid == 0) {
printf("Hi father! I‘m a ZOMBIE/n");
exit(0); //(1)
}
else {
sleep(10);
wait(NULL); //(2)
}
}

(1) 向父进程发送SIGCHILD信号
(2) 父进程处理SIGCHILD信号

执行exit(0)时根据其父进程的状态决定自己的状态:
如果父进程已经退出(没有wait),则该子进程将会成为孤儿进程过继给init进程
如果其父进程还没有退出,也没有wait(),那么该进程将向父进程发送SIGCHILD信号,进入僵尸状态等待父进程为其收尸。如果父进程一直没有执行wait(),那么该子进程将会持续处于僵尸状态,如果父进程到死也没有执行wait则在死后会将zombie进程过继给init进程,由init进程来处理zombie进程,最终还是会死掉。

子进程将成为孤儿进程
------------------------------------------------------
#include 
#include 
#include 
#include

main()
{
pid_t pid;
pid = fork();
if(pid < 0)
printf("error occurred!/n");
else if(pid == 0) {
sleep(6);
printf("I‘m a orphan/n");
exit(0);
}
else {
sleep(1);
printf("Children Bye!/n");
}
}

# ./a.out
Children Bye!
# I‘m a orphan
(回车后将会进入#)
#

二、有什么害处:
僵尸进程会占用系统资源,如果很多,则会严重影响服务器的性能
孤儿进程不会占用系统资源,最终是由init进程托管,由init进程来释放它。
处理流程:
只要老爹不等wait(sys/wait.h)儿子,儿子都将成为孤魂野鬼zombie(zombie),unix中默认老爹总是想看儿子死后的状态(以便报仇) 
if 老爹比儿子先再见 
儿子将被init(id = 1)收养,最后的结果是zombie儿子彻底再见,系统资源释放 
else 

儿子的zombie将一直存在,系统资源占用... 
if 老爹dead 
儿子将被init(id = 1)收养,最后的结果是zombie儿子彻底再见,系统资源释放

else 类似的儿子zombie越来越多,系统就等死了!!! 
}

signal(SIGCHLD, SIG_IGN); //忽略SIGCHLD信号,这常用于并发服务器的性能的一个技巧
//因为并发服务器常常fork很多子进程,子进程终结之后需要
//服务器进程去wait清理资源。如果将此信号的处理方式设为
//忽略,可让内核把僵尸子进程转交给init进程去处理,省去了
//大量僵尸进程占用系统资源。(Linux Only)

三、如何防止僵尸进程
首先明白如何产生僵尸进程:
1、子进程结束后向父进程发出SIGCHLD信号,父进程默认忽略了它
2、父进程没有调用wait()或waitpid()函数来等待子进程的结束
第一种方法: 捕捉SIGCHLD信号,并在信号处理函数里面调用wait函数
转贴Richard Steven的Unix Network Programming代码

int
main(int argc, char **argv)
{
...
Signal(SIGCHLD, sig_chld);
for(;
}
...
}

void
sig_chld(int signo)
{
pid_t pid;
int stat;

while ( (pid = waitpid(-1, &stat, WNOHANG)) >; 0)
printf("child %d terminated/n", pid);
return;
}

第二种方法:两次fork():转载
在《Unix 环境高级编程》里关于这个在8.6节有非常清楚的说明。

实例
回忆一下8 . 5节中有关僵死进程的讨论。如果一个进程要f o r k一个子进程,但不要求它等待
子进程终止,也不希望子进程处于僵死状态直到父进程终止,实现这一要求的诀窍是调用f o r k
两次。程序8 - 5实现了这一点。
在第二个子进程中调用s l e e p以保证在打印父进程I D时第一个子进程已终止。在f o r k之后,
父、子进程都可继续执行——我们无法预知哪一个会先执行。如果不使第二个子进程睡眠,则
在f o r k之后,它可能比其父进程先执行,于是它打印的父进程I D将是创建它的父进程,而不是
i n i t进程(进程ID 1)。

#include 
#include 
#include "ourhdr.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/n", 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);
}
//avoid zombie process by forking twice

本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/metasearch/archive/2008/05/31/2498853.aspx

时间: 2024-10-10 05:49:38

孤儿进程和僵尸进程的相关文章

孤儿进程与僵尸进程[总结]

http://www.cnblogs.com/Anker/p/3271773.htm 1.前言 之前在看<unix环境高级编程>第八章进程时候,提到孤儿进程和僵尸进程,一直对这两个概念比较模糊.今天被人问到什么是孤儿进程和僵尸进程,会带来什么问题,怎么解决,我只停留在概念上面,没有深入,倍感惭愧.晚上回来google了一下,再次参考APUE,认真总结一下,加深理解. 2.基本概念 我们知道在unix/linux中,正常情况下,子进程是通过父进程创建的,子进程在创建新的进程.子进程的结束和父进程

快速理解孤儿进程和僵尸进程

下面是我大约11年前在读APUE(<Unix环境高级编程>)对孤儿进程和僵尸进程的理解,为了便于记忆,采用打比方的方式予以解释. (当然不一定精准,后面我会贴出wikipedia上的专业解释.) 操作系统OS好比一个公司,公司的CEO就是init进程. 任何一个子进程都有父进程,就好比任何一个人都有爹. 这里假定子进程为小明,父进程为小明的爸爸. init进程作为OS公司的CEO,是小明的爷爷(注:小明的爸爸很可能是CEO的第N代后人,N>=1,这里假定N=1). 任何一个进程在退出之后

【Linux】孤儿进程和僵尸进程

本文转载自:http://www.cnblogs.com/anker/p/3271773.html 并做了小幅修改. 1.基本概念 我们知道在unix/linux中,正常情况下,子进程是通过父进程创建的,子进程在创建新的进程.子进程的结束和父进程的运行是一个异步过程,即父进程永远无法预测子进程 到底什么时候结束. 当一个 进程完成它的工作终止之后,它的父进程需要调用wait()或者waitpid()系统调用取得子进程的终止状态. 孤儿进程:一个父进程退出,而它的一个或多个子进程还在运行,那么那些

wait函数返回值总结,孤儿进程与僵尸进程[总结]

http://blog.csdn.net/astrotycoon/article/details/41172389 wait函数返回值总结 http://www.cnblogs.com/Anker/p/3271773.html 孤儿进程与僵尸进程[总结]

进程与线程(三) 孤儿进程与僵尸进程

具体细节可参考: http://www.cnblogs.com/Anker/p/3271773.html 本文只是用最小的语言总结: 两者对比:(爹是父进程,孩子是子进程) 爹没了,孩子还在,孩子就是孤儿进程,孤儿被(init)收养. 爹在,孩子在,但是爹不管孩子了,因为有爹又不能收养,此时的孩子就是僵尸进程. 1.你知道什么是僵尸进程,(对系统有害),如何产生的? 僵尸进程不是活着的进程,可以说就是一个数据结构,它是已经完成的任务的进程,但是不是它完成任务后就会烟消云散的,他会留下一点东西,这

孤儿进程与僵尸进程【比较】

今天在群里聊起僵尸进程,才发现自己把僵尸进程和孤儿进程搞混了,简直不能原谅.速度查了一下,原来如此.感谢原作者的分享,如下:    1.基本概念 我们知道在unix/linux中,正常情况下,子进程是通过父进程创建的,子进程在创建新的进程.子进程的结束和父进程的运行是一个异步过程,即父进程永远无法预测子进程 到底什么时候结束. 当一个 进程完成它的工作终止之后,它的父进程需要调用wait()或者waitpid()系统调用取得子进程的终止状态. 孤儿进程:一个父进程退出,而它的一个或多个子进程还在

(转)进程间关系:进程、僵尸进程、孤儿进程、进程组、前台进程组、后台进程组、孤儿进程组、会话、控制终端

不同的shell对使用管道线时创建子进程的顺序不同,本文以bash为例,它是支持作业控制的shell的典型代表. 僵尸进程与孤儿进程 僵尸进程:先于父进程终止,但是父进程没有对其进行善后处理(获取终止子进程有关信息,释放它仍占有的资源).消灭僵尸进程的唯一方法是终止其父进程.孤儿进程:该进程的父进程先于自身终止.其特点是PPID=1(init进程的ID).一个孤儿进程可以自成孤儿进程组. 文中用到的缩写 PID = 进程ID (由内核根据延迟重用算法生成)PPID = 父进程ID(只能由内核修改

孤儿进程与僵尸进程[总结](转载)

1.前言 之前在看<unix环境高级编程>第八章进程时候,提到孤儿进程和僵尸进程,一直对这两个概念比较模糊.今天被人问到什么是孤儿进程和僵尸进 程,会带来什么问题,怎么解决,我只停留在概念上面,没有深入,倍感惭愧.晚上回来google了一下,再次参考APUE,认真总结一下,加深理解. 2.基本概念 我们知道在unix/linux中,正常情况下,子进程是通过父进程创建的,子进程在创建新的进程.子进程的结束和父进程的运行是一个异步过程,即父进程永远无法预测子进程 到底什么时候结束. 当一个 进程完

linux 孤儿进程和僵尸进程

孤儿进程和僵尸进程: 如果父进程先退出,子进程还没退出那么子进程的父进程将变成init进程(任何一个进程都有一个父进程) 如果子进程先退出,父进程还没有退出,那么子进程必须要等到父进程捕获到了子进程的退出状态才真正结束,否则这个时候子进程就成为僵尸进程. 如果父进程先结束,子进程会托孤给1号进程 怎样避免僵尸进程呢?是由于父进程没有给子进程收尸,怎么解决这个问题呢.父进程再创建子进程的时候,利用singal(sigchild,sig_ing) 告诉内核不管子进程的生命周期. 本文来源:http: