Linux如何避免僵死进程

本文介绍两种避免僵尸进程的方法:一是忽略SIGCLD信号,二是通过两次深度fork()创建孤儿进程,由init进程回收。文中提供了具体的C语言示例代码。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

/* OS: CentOS
 * gcc avoid_zombie.c -o avoid_zombie
*/
#include <stdio.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <unistd.h>
#include <errno.h>
#include <sys/types.h>

int main(int argc, char *argv[])
{
	int ret=0;
	pid_t pid;
	
	//signal(SIGCHLD, SIG_IGN); //可以避免子进程成为僵尸进程
	
	pid = fork(); // pid=子进程的进程号
	if( pid < 0 )
	{
		perror("fail to fork");
		exit(1);
	}	
	else if( pid == 0 ) //child process(pid)
	{
		int pid2;
		pid2 = fork();
		if( pid2 < 0 ) {
			perror("fail to fork");	
			exit(1);
		}
		else if( pid2 == 0 ) { // grandson process(ppid == pid), do some job.
			printf("grandson process begin, pid=%d, ppid=%d\n", getpid(),getppid());
			sleep(10);
			// do some job... 要做的工作放在孙进程执行
			printf("grandson process exit, pid=%d, ppid=%d\n", getpid(),getppid());
			exit(0);
		}
		else {	// child process(pid), exit.
			sleep(5);
			printf("child process exit, pid=%d, ppid=%d\n", getpid(),getppid());
			exit(2);
		}
		
	}
	else
	{
		sleep(20);	
		//5秒后当子进程退出,这个时间用ps ax | grep avoid_zombie 查看,会有一个“Z+”的僵尸进程
		//10秒后当孙进程退出,这个时间用ps ax | grep avoid_zombie 查看,
		//还是只有一个“Z+”的僵尸进程(子进程),此时孙进程已成为孤儿进程,孙进程由init进程回收,
		//孙进程不会成为僵尸进程
		
		//(1)若主进程没有设置signal(SIGCHLD, SIG_IGN),则必须调用wait/waitpid回收子进程.
		//(2)若主进程设置了signal(SIGCHLD, SIG_IGN),子进程不会变为僵尸进程,
		//	 所以主进程无需调用waitpid回收子进程,调用waipid会返回失败。
		//参考man waitpid的notes部分:
		//if the disposition of SIGCHLD is set to SIG_IGN  or  the
       	//SA_NOCLDWAIT  flag  is set for SIGCHLD (see sigaction(2)), then children that termi-
       	//nate do not become zombies and a call to wait() or waitpid() will  block  until  all
       	//children  have  terminated,  and  then fail with errno set to ECHILD.
		
		int status=0;
		do {
			ret = waitpid(pid, &status, WUNTRACED | WCONTINUED);
			if (ret == -1) {
			   perror("waitpid");
			   exit(EXIT_FAILURE);
			}
			
			if (WIFEXITED(status)) {
			   printf("child[%d] exited, status=%d\n", ret, WEXITSTATUS(status));
			} else if (WIFSIGNALED(status)) {
			   printf("killed by signal %d\n", WTERMSIG(status));
			} else if (WIFSTOPPED(status)) {
			   printf("stopped by signal %d\n", WSTOPSIG(status));
			} else if (WIFCONTINUED(status)) {
			   printf("continued\n");
			}
       } while (!WIFEXITED(status) && !WIFSIGNALED(status));
       
		sleep(10);	
	}
	
	return EXIT_SUCCESS;
	
}

僵尸进程的避免方法:

方法一:

    忽略SIGCLD信号:signal(SIGCHLD, SIG_IGN),系统将不产生僵死进程。
方法二:

    两次深度fork(),子进程退出,让孙子进程成为孤儿进程,从而init进程将负责清除这个孤儿进程。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值