在Linux系統中,殭屍進程是已經執行完畢,但是沒有被父進程回收的子進程。判斷殭屍進程的一個方法是使用ps命令查看進程狀態。如果進程狀態是Z,說明這是一個殭屍進程。
在多進程的程序中,父進程會啓動若干個子進程來處理任務。當子進程退出後,除了在進程表中佔用的一個進程表項,子進程所使用的資源(文件描述符、內存等)都會被釋放。保留子進程的進程表項,是爲了把子進程的執行結果告訴給父進程。父進程調用waitpid()來得到子進程的執行結果。
如果子進程執行完畢,而父進程沒有退出,也沒有調用waitpid()來得到子進程的執行結果,這時,子進程已經不存在了,卻還佔用着一個進程表項。這樣的進程叫做殭屍進程。當父進程調用waitpid()後,殭屍進程佔用的進程表項被釋放,殭屍進程徹底消失。
如果父進程在調用waitpid前退出,子進程(包括殭屍進程)的父進程會變爲init進程。由init進程負責回收子進程,所以不會產生殭屍進程。
殭屍進程消耗的唯一資源是進程表項。也就是說,如果產生了大量的殭屍進程佔滿了進程表,系統將無法創建新的進程。除此之外,殭屍進程不會對系統造成影響。
殭屍進程不能使用kill來殺死。因爲殭屍進程已經執行完畢了,無法殺死。要消除殭屍進程,方法是找到父進程,殺死父進程。這時殭屍進程會由init收回。
下面是一個展示殭屍進程產生原因的例子。
/*
展示Linux系統中殭屍進程的產生原因。
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
int main(void){
pid_t pid;
if ((pid = fork()) < 0){
perror("");
exit(0);
} else if (pid == 0){
exit(0);
} else {
char ch;
char buffer[1024];
int status;
printf("See the zombie process?\n");
printf("child process pid: %d\n", pid);
sprintf(buffer, "ps -ef | grep %d\0", pid);
printf("execute '%s'\n", buffer);
system(buffer);
waitpid(pid, &status, 0);
printf("It's gone.\n");
printf("execute '%s'\n", buffer);
printf("child process (%d) exited with status: %d\n", pid, status);
system(buffer);
}
return 0;
}