僵死进程与孤儿进程

原创 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.孤儿进程

孤儿进程与僵死进程

基本概念  孤儿进程:一个父进程退出,而它的一个或多个子进程还在运行,那么那些子进程将成为孤儿进程。孤儿进程将被init进程(进程号为1)所收养,并由init进程对它们完成状态收集工作。  僵尸进程:...
  • centor
  • centor
  • 2017年04月23日 16:38
  • 149

孤儿进程、僵死进程

进程终止 有3种正常终止方法、2中异常终止方法。 正常终止: 1 main函数内执行return语句。 2 调用exit函数,其操作包括调用各终止处理程序(调用atexit时登记),关闭所有标准IO流...

僵死进程和孤儿进程

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

Unix进程关系—僵死进程与孤儿进程

如果父进程在子进程之前终止,子进程先成为孤儿进程,此后子进程的父进程将变为init进程。我们称这些进程由init进程领养。其操作过程大致是:在一个进程终止时,内核逐个检查所有活动进程,以判断它是否是正...

特殊进程之孤儿进程测试代码

  • 2015年05月25日 15:12
  • 546B
  • 下载

《UNIX环境高级编程》笔记--孤儿进程组

POSIX.1将孤儿进程组定义为:该组中每个成员的父进程要么是该组的一个成员,要么不是该组所属会话的成员。一个进程组 不是孤儿进程组的条件是:该组中有一个进程,其父进程在属于同一会话中的另一个组中。...
  • TODD911
  • TODD911
  • 2013年12月01日 13:35
  • 2271

Ubuntu下孤儿进程问题

在学习Linux c编程实战的进程控制一章时,书上关于孤儿进程的例子如下:#include #include #include #include int main(){ pid_t pid; ...

孤儿进程

孤儿进程即父进程先于子进程终止的进程,会被init接管,其父进程变为1。 孤儿进程组的概念:组中每个成员的父进程要么是该组的一个成员,要么不是该组所属会话的成员。 一个进程组不是孤儿进程组的条件:...

浅谈 upstart 和 孤儿进程问题!!!

这是好久之前看的了,我那个时候就有一个问题没有弄清楚,现在总算是明白了一点点,总比没有明白强吧, 首先我得说一下我使用的系统 是 Ubuntu 14:04.5 X64 。 为什么要说一下系统呢,因...

孤儿进程组和终端会话

孤儿进程: 即一个其父进程已经终止的进程。 孤儿进程由 init 进程“收养”,init 进程ID为1,因此被收养的孤儿进程的父进程便更新为1。 孤儿进程组: 一个进程组中的所有进程的父进程要么是该...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:僵死进程与孤儿进程
举报原因:
原因补充:

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