首先關於孤兒進程
processA processB processC
ps -ef|grep process
sroot 9665 24982 0 23:42 pts/0 00:00:00 /bin/bash ./processA.sh
sroot 9666 9665 023:42 pts/0 00:00:00 /bin/bash./processB.sh
sroot 9667 9666 023:42 pts/0 00:00:00 /bin/bash./processC.sh
24982 -> 9665 /processA.sh ->9666 ./processB.sh ->9667 ./processC.sh
24982是INIT下/bin/bash .
[sroot@AAEP7151 24982]# pwd
/proc/24982
[sroot@AAEP7151 24982]# ll
total 0
lrwxrwxrwx. 1 sroot root 0 Jun 22 23:45 cwd -> /home/craft/shell
-r--------. 1 sroot root 0 Jun 22 23:45 environ
lrwxrwxrwx. 1 sroot root 0 Jun 22 23:32 exe -> /bin/bash
[sroot@AAEP7151 24982]# ps -ef |grep 24982
sroot 9665 24982 0 23:42 pts/0 00:00:00 /bin/bash ./processA.sh
sroot 19995 2740 023:47 pts/1 00:00:00 grep 24982
sroot 24982 24935 0 23:32 pts/0 00:00:00 bash
之後,kill -9 processB 看A和C的變化
[sroot@AAEP7151 24982]# ps aux |grep process
sroot 17693 0.0 0.0 106104 1172 pts/0 S+ 00:22 0:00 /bin/bash./processA.sh
sroot 17694 0.0 0.0 106104 1172 pts/0 S+ 00:22 0:00 /bin/bash./processB.sh
sroot 17695 32.8 0.0 106108 1192 pts/0 S+ 00:22 0:01 /bin/bash ./processC.sh
ps aux |grep process
只剩下一個/processC.sh,A和B 都不見了
sroot 17695 36.2 0.0 106108 1192 pts/0 R 00:22 0:12 /bin/bash ./processC.sh
也就是B死掉的時候,會去通知他的父進程A。
本身A的存在就是等待B 完成的,所以B死掉,A也釋放了。
但是C並不知道。
這個時候A不停的繼續跑,並且無法用ctrl+c結束。
知道kill -9 processC的進程號。
這個時候並不會產生殭屍進程
此時,C就是孤兒進程。
如何產生殭屍進程
首先,殭屍進程是由於父進程沒有回收子進程。
父進程會使用wait函數來等待子進程若子進程結束,用這個函數來回收子進程。
#include <stdio.h>
#include <sys/types.h>
#include <time.h>
int main()
{
//fork a child process
pid_t pid = fork(); 產生一個子進程。新產生的子進程同樣用這個代碼。這樣就會有兩個程序在使用同一個代碼運行。
if (pid > 0) //parentprocess父進程進入這個if判斷。
{
printf("in parentprocess, sleep for one miniute...zZ...\n");
struct timeval tv;
gettimeofday(&tv,NULL);
printf("parent microsecond:%ld\n",tv.tv_sec*1000000 +tv.tv_usec); //微秒 輸出當前的時間
sleep(60);
printf("aftersleeping, and exit!\n");
gettimeofday(&tv,NULL);
printf("parentmicrosecond after sleeping:%ld\n",tv.tv_sec*1000000 + tv.tv_usec); //微秒
重新輸出sleep之後的時間
}
else if (pid == 0) 子進程進入這個if判斷語句
{
//child process exit,and to be a zombie process
printf("in child process, and exit!\n");
structtimeval tv;
gettimeofday(&tv,NULL);
printf("child microsecond:%ld\n",tv.tv_sec*1000000 +tv.tv_usec); //微秒
輸出進入到子進程的時間
}
}
用gcc指令編譯
[root@localhost test]# gcc zombie1.c -o zombie1
[root@localhost test]# ./zombie1 運行
運行結果如下
./zombie1
in parent process, sleep for one miniute...zZ...父進程先進入第一個判斷語句,輸出時間
parent microsecond:1498469853526179
in child process, and exit! 子進程進入判斷語句,輸出時間
child microsecond:1498469853526404
after sleeping, and exit!
parent microsecond aftersleeping:1498469913532272 父進程結束sleep,輸出時間,這個時間跟第一個輸出時間相差爲60s。
用ps查看進程情況
[root@localhost test]# ps aux |grep zombie
root 3445 0.0 0.0 3924 416 pts/2 S+ 05:37 0:00 ./zombie1
root 3446 0.0 0.0 0 0 pts/2 Z+ 05:37 0:00 [zombie1]<defunct>
出現一個殭屍進程
[root@localhost test]# ps -ef |grep zomb
root 3445 3024 0 05:37 pts/2 00:00:00./zombie1
root 3446 3445 0 05:37 pts/2 00:00:00 [zombie1] <defunct>
從進程ID能看出這個殭屍進程是zombie的子進程
改進程序,來更好的觀察由於父進程是否調用wait帶來的結果。
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main()
{
int i = 0;
char cCmd = 'a';
char cTmp = 'a';
printf("process start with pid: %d\n", getpid());
pid_t pid = fork();
switch (pid)
{
case 0:
{
printf("child_process start with pid: %d\n", getpid());
printf("child_process exit\n");
exit(1);
}
break;
case -1:
break;
default:
{
while (1)
{
printf("Input 'q' to exit without recycle the resource of child and will generate zombile process.\n");
printf("Input 'Q' to recyle resource of child.\n");
printf("No matter q or Q , the parent process will exit .\n");
cCmd = getchar();
while ((cTmp = getchar()) != '\n');
if (cCmd == 'q')
{
printf(" exit without recycle the resource of child ,generate zombile process.Please use ps command to check\n");
break;
}
else if (cCmd == 'Q')
{
printf(" Parent process will recycle the child resource .wait child_process to exit\n");
wait(NULL);
printf("Child process was recycled ,the zombile process was clear.press any key to continue...\n");
cTmp = getchar();
while ((cTmp = getchar()) != '\n');
break;
}
else
{
printf("You input %c. can not be recognized by this program Please reinput\n", cCmd);
}
}
}
break;
}
printf("Parent_process exit\n");
return 0;
}
設置了判斷語句讓用戶輸入,在子進程結束的時候,產生殭屍進程。
若用戶輸入q,則調用wait函數回收該殭屍進程父進程再退出。
若用戶輸入Q,則不調用wait函數回收,直接退出。
[root@localhost fish]# ./zombile
process start with pid: 23216
Input 'q' to exit without recycle the resource of child and will generate zombil
Input 'Q' to recyle resource of child.
No matter q or Q , the parent process will exit .
child_process start with pid: 23217
child_process exit
此時查看進程發現產生了殭屍進程
[root@localhost ~]# ps -ef |grep zombile
root 23216 22233 0 17:34 pts/1 00:00:00 ./zombile
root 23217 23216 0 17:34 pts/1 00:00:00 [zombile] <defunct>
root 23223 22391 0 17:34 pts/2 00:00:00 grep zombile
Q
Parent process will recycle the child resource .wait child_process to exit
Child process was recycled ,the zombile process was clear.press any key to continue...
運行該程序發現,在使用wait之後,殭屍子進程就消失了。
[root@localhost ~]# ps -ef |grep zombile
root 23216 22233 0 17:34 pts/1 00:00:00 ./zombile
root 23225 22391 0 17:34 pts/2 00:00:00 grep zombile
只剩下父進程自己。
此時如果直接退出該程序,退出父進程,子進程也會跟着消失,可見,清除父進程是清楚殭屍子進程的方法之一。
kill掉defunct進程方法有二:
1,重啓服務器電腦,這個是最簡單,最易用的方法,但是如果你服務器電腦上運行有其他的程序,那麼這個方法,代價很大。
所以,儘量使用下面一種方法2,找到該defunct殭屍進程的父進程,將該進程的父進程殺掉,則此defunct進程將自動消失。