僵死进程与孤儿进程

原创 2016年05月31日 16:47:02

1.僵死进程与孤儿进程

僵死进程:进程已经退出,但是没有回收内核 PCB 资源的进程叫僵死进程。

孤儿进程:父亲进程先于子进程退出后,这个子进程就是孤儿进程,父亲进程会被转移为 init(pid=1)进程。


僵死进程示例:

#include <stdio.h>
#include <stdlib.h>
#include "apue.h"
#include <sys/wait.h>

void test(int i , void *arg)
{
    printf("helloworld,%d,%s\n",i,(char*)arg);
}

int main(int argc,char *argv[])
{
    pid_t pid = fork();
    if(pid == -1)
    {
        perror("fork");
    }
    else if(pid == 0)
    {
        sleep(2);
        printf("child pid:%d\n",getpid());
        exit(10);
    }
    else
    {
        int status;
        pid_t w_pid;
        sleep(20);
        w_pid = waitpid(-1,&status,0);
        printf("w_pid:%d,status:%d\n",w_pid,status>>8);
    }

    exit(0);
}

父进程sleep 20秒时,子进程已经退出,但是没有回收PCB资源(进程PCB资源由父进程回收)。


孤儿进程示例:

#include <stdio.h>
#include <stdlib.h>
#include "apue.h"
#include <sys/wait.h>

void test(int i , void *arg)
{
    printf("helloworld,%d,%s\n",i,(char*)arg);
}

int main(int argc,char *argv[])
{
    pid_t pid = fork();
    if(pid == -1)
    {
        perror("fork");
    }
    else if(pid == 0)//子进程
    {
        printf("child pid:%d,parent pid:%d\n",getpid(),getppid());
        sleep(4);
        printf("child pid:%d,parent pid:%d\n",getpid(),getppid());
        exit(10);
    }
    else//父进程
    {
        sleep(2);
        exit(0);
    }
    return 0;
}
父进程比子进程先退出了,子进程由pid==1的进程监管。




2.僵死进程

2.1僵死进程的原因及危害

一个进程在调用exit命令结束自己的生命的时候,其实他并没有真正的被销毁,而是留下一个称为僵尸进程(Zombie)的数据结构(系统调用exit,他的作用是使进程退出,但是也仅仅限于一个正常的进程变成了一个僵尸进程,并不能完全将其销毁)。在linux进程的状态中,僵尸进程是非常特殊的一种,它已经放弃了几乎所有的内存空间,没有任何可执行代码,也不能被调度,仅仅在进程列表中保留一个位置,记载该进程的退出状态信息供其他进程收集,除此之外,僵尸进程不再占有任何存储空间。他需要他的父进程来为他收尸,如果他的父进程没有安装SIGCHLD信号处理函数调用wait 或 waitpid() 等待子进程结束,有没有显式忽略该信号,那么它就一直保持僵尸状态,如果这时候父进程结束了,那么init进程会自动接手这个子进程,为他收尸,他还是能被清除掉的。但是如果父进程是一个循环,不会结束,那么子进程就会一直保持僵尸状态,这就是系统中为什么有时候会有很多的僵尸进程。


由此看出,僵死进程并不会佔用很多的资源。唯一的危害是影响了系统最大进程数,有可能造成后续进程无法分配资源。


2.2.僵死进程演示:

代码:

<span style="font-size:18px;">#include<stdio.h>
#include "apue.h"
#include "fcntl.h"
#include <sys/wait.h>
static void sig_int(int);
#define BUFFSIZE 4096
int glob = 6;
char buf[] = "a write to stdout\n";
const char cmd_init[]="ps -o pid,ppid,state,tty,command"; 
int main(int argc,char *argv[])
{
	int var;
	pid_t pid;
	var = 88;
	if(write(STDOUT_FILENO,buf,sizeof(buf)-1)!=sizeof(buf)-1)
		err_sys("write error");
	printf("before fork\n");
	if((pid = fork())<0)
	{
		err_sys("fork error");
	}
	else if(pid == 0)
	{
		glob++;//子进程运行
		var++;
	}
	else
	{
		sleep(60);//父进程运行
	}
	printf("pid = %d,glob = %d,var = %d\n",getpid(),glob,var);  
	exit(0);
}</span>



查看僵死进程:ps auwx | cut -c 10-15,45-50,63- | grep -i Z 查看僵尸进程pid、名称和进程路径。

僵尸进程的状态为Z,如下图的[first]



2.3.避免zombie的方法
1)在svr4中,如果调用signal或是sigset将SIGCHLD的配置设置为忽略,则不会产生僵死子进程。另外,使用svr4版本sigaction,则可设置SA_NOCLDWAIT标志以避免子进程僵死。Linux中也可以使用这个,在一个程序开始调用这个函数signal(SIGCHLD,SIG_IGN);

2)调用fork两次:第一次调用fork创建子进程,第二次调用创建孙子进程,当子进程退出后,不管父进程是否在循环运行,孙子进程都被init进程接手了,不会产生僵死进程。示例代码:

<span style="font-size:18px;">#include<stdio.h>
#include "apue.h"
#include "fcntl.h"
#include <sys/wait.h>
#define BUFFSIZE 4096
int main(int argc,char *argv[])
{
	pid_t pid;
	if((pid = fork())<0)
		err_sys("fork error");
	else if(pid == 0)//第一个子进程创建
	{	
		if((pid = fork())<0)//第二个子进程创建
			err_sys("fork error");
		else if(pid > 0)
			exit(0);//第一个子进程退出,第二个子进程被init进程托管,不会成为僵死进程
		//第二个子进程运行
		sleep(2);
		printf("second child,parent pid = %d\n",getppid());
		exit(0);
	}
	if(waitpid(pid,NULL,0)!=pid)//父进程:等待第一个子进程退出
		err_sys("fork error");
	 
	exit(0);
}</span>



3)用waitpid等待子进程返回。


3.孤儿进程

僵死进程与孤儿进程

1.僵死进程的原因及危害 一个进程在调用exit命令结束自己的生命的时候,其实他并没有真正的被销毁,而是留下一个称为僵尸进程(Zombie)的数据结构(系统调用exit,他的作用是使进程退出,但是也仅...
  • ceasadan
  • ceasadan
  • 2016年05月31日 16:47
  • 352

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

2、基本概念   我们知道在unix/linux中,正常情况下,子进程是通过父进程创建的,子进程在创建新的进程。子进程的结束和父进程的运行是一个异步过程,即父进程永远无法预测子进程 到底什么时候...
  • chaoshui7758
  • chaoshui7758
  • 2015年09月25日 10:54
  • 108

1.练习:在一个孤儿进程中创建十个僵尸进程

一个僵尸进程是在父进程有机会用wait或waitpid收集它退出状态之前就终止的进程。   子所以被称为僵尸进程是因为进程虽然结束了,但依然在进程表中存在。 子进程退出后分配给它的内存和资源都被释放,...
  • lingdi2000
  • lingdi2000
  • 2015年04月23日 15:10
  • 837

编写一个孤儿进程,这个孤儿进程可以同时创建100个僵死进程

这道题程序很简单,我就不贴出来了,主要是理解孤儿进程和僵死进程。 孤儿进程:父进程在子进程退出前退出了,只有儿子在了。但是这样init进程会接管这些孤儿,wait并释放了pid,所以孤儿进程没什么危...
  • wwssttcc
  • wwssttcc
  • 2015年10月24日 17:25
  • 818

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

1、前言   之前在看《unix环境高级编程》第八章进程时候,提到孤儿进程和僵尸进程,一直对这两个概念比较模糊。今天被人问到什么是孤儿进程和僵尸进程,会带来什么问题,怎么解决,我只停留在概念上面,没...
  • gettogetto
  • gettogetto
  • 2017年03月06日 09:51
  • 124

孤儿进程与僵尸进程

使用第三方软件时,发现系统进程数异常,通过命令 ps - ef | grep defunct 发现很多僵尸进程,最后通过kill掉父进程,并修复了该BUG。 网上相关的资料很多很多,下面对孤儿进程和僵...
  • daiyudong2020
  • daiyudong2020
  • 2015年12月12日 00:09
  • 873

Linux编写一个孤儿进程,这个孤儿进程可以同时创建100个僵死进程。

#include #include #include #include #include #include #include #include #include int main(...
  • HelloNiGeSB
  • HelloNiGeSB
  • 2016年07月09日 12:51
  • 884

python中的孤儿进程

1.子进程未运行完父进程就结束运行退出,留下来的子进程就是孤儿进程   2.父进程结束退出,子进程会被继父收回,通常是int进程(pid为1)无危害   import os import t...
  • xun527
  • xun527
  • 2017年08月09日 22:36
  • 225

僵死进程和孤儿进程

from: http://blog.chinaunix.net/uid-7897183-id-75583.html 在Unix系统编程中,常常会碰到两个概念:僵死进程和孤儿进程。话说我以...
  • yygydjkthh
  • yygydjkthh
  • 2012年03月11日 15:03
  • 772

孤儿进程与僵尸进程

早就了解孤儿进程与僵尸进程,但仅仅是停留在一知半解的程度,总结一下。概念  首先我们知道在Linux中,进程都是由父进程创建的,一般情况下子进程退出后需要父进程来清理子进程退出后留下的“垃圾”,父进程...
  • lyc_stronger
  • lyc_stronger
  • 2016年07月28日 20:25
  • 538
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:僵死进程与孤儿进程
举报原因:
原因补充:

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