天天看點

linux 僵屍(defunct)程序和孤兒程序

在fork或者exec函數建立一個新的程序,為了收集新程序的退出狀态并防止出現僵屍程序(zombie process),父程序應該調用waitpid或者wait等待子程序退出。

在unix/linux 系統中,一個子程序結束了,但是它的父程序沒有等待(調用wait / waitpid)它(前提是它的父程序沒有退出,這裡面作業系統認為它有父程序,作業系統不會清除該程序), 那麼它将變成一個僵屍程序,如果父程序也接着退出的話,作業系統會統一将其清除。

之是以被稱為僵屍程序,因為它雖然死掉了,但是在程序表中依然存在。子程序退出後分的記憶體和其他資源都被釋放,但它還是在核心程序表中保留一條,核心在父程序回收子程序的退出狀态前一直保留它。有一兩個僵屍程序不算什麼,但是一旦程式頻繁的執行fork 或者exec卻又不能收集退出狀态,那麼最終、将會填滿程序表這會影響性能,可能導緻系統重新開機。

#include <stdio.h>
#include <stdlib.h>
#include<unistd.h>
#include<sys/types.h>
#include <string.h>
#include <errno.h>

int main(void)
{
	pid_t pid = fork();
	if (pid == -1)
	{
		printf("%s \n", strerror(errno));
		return -1;
	}
	if (pid == 0)
	{
		printf("child exit!");
		exit(0); //子程序直接退出
	}
	else
	{
		printf("parent sleep 100s\n"); //父程序沒有調用waitpid去等待子程序退出
		sleep(100);
	}
	return 0;
}
           
linux 僵屍(defunct)程式和孤兒程式

通過ps指令這裡使用ps -u hsc (這裡hsc是使用者名),我們可以看到zombie_test程序有<defunct>defunct的意思就是已死的,無效的,不存在的。

linux 僵屍(defunct)程式和孤兒程式

如果子程序的父程序已經先結束了,此時而它的一個或多個子程序還在運作,這些子程序将成為孤兒程序,它們将由init程序收養。因為每個程序結束的時候,系統都會掃描目前系統中所運作的所有程序, 看有沒有哪個程序是剛剛結束的這個程序的子程序,如果是的話,就由Init 來接管他,成為它的父程序……孤兒程序是正常的,不會給系統帶來問題。

/*
 * main.c
 *
 *  Created on: 2015-1-29
 *      Author: hsc
 */

#include <stdio.h>
#include <stdlib.h>
#include<unistd.h>
#include<sys/types.h>
#include <sys/wait.h>
#include <string.h>
#include <errno.h>

int main(void)
{
	pid_t pid = fork();
	if (pid == -1)
	{
		printf("%s \n", strerror(errno));
		return -1;
	}
	if (pid == 0)
	{
		while(1)
		{
			sleep(1);
			printf("child ppid=%d \n",getppid()); //列印出其父程序pid
		}

	}
	else
	{
		printf("parent exit\n"); //父程序直接退出
		exit(0);
	}
	return 0;
}

           
linux 僵屍(defunct)程式和孤兒程式

可以看到父程序退出後子程序的父程序的pid為1(init 程序)。

繼續閱讀