在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;
}
通過ps指令這裡使用ps -u hsc (這裡hsc是使用者名),我們可以看到zombie_test程序有<defunct>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;
}
可以看到父程序退出後子程序的父程序的pid為1(init 程序)。