1.腳本如下:
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
int main()
{
if ( fork() != 0 )
{
printf("I am parent,PID=%d\n",getpid()); //輸出父進程的id,父進程運行50s
sleep(50);
}
else
{
if ( fork() != 0)
{
sleep(10);
printf("I am child,PID=%d\n",getpid()); //輸出子進程的id,子進程運行10s
}
else
{
sleep(30);
printf("I am sun-child,PID=%d\n",getpid()); //輸出孫子進程的id,孫子進程運行30s
}
}
return 0;
}
執行結果:
[root@demo Desktop]# ./fork1
I am parent,PID=29195 ---->執行時立即輸出
I am child,PID=29196 ---->10s後子進程輸出
I am sun-child,PID=29197---->30後孫子進程輸出
1.執行./fork1後的輸出,I am parent,PID=29195,查看進程pid如下,
有3個fork1進程,分別是父進程29195,子進程29196,孫子進程29197
[root@demo ~]# ps -al
F S UID PID PPID C PRI NI ADDR SZ WCHAN TTY TIME CMD
0 S 0 29195 5701 0 77 0 - 379 - pts/4 00:00:00 fork1
1 S 0 29196 29195 0 78 0 - 378 - pts/4 00:00:00 fork1
1 S 0 29197 29196 0 78 0 - 378 - pts/4 00:00:00 fork1
4 R 0 29198 16372 0 78 0 - 1051 - pts/1 00:00:00 ps
4 S 0 29507 21039 0 77 0 - 1222 wait pts/2 00:00:00 su
4 S 508 29508 29507 0 75 0 - 1132 - pts/2 00:00:00 bash
2.10s後,子進程結束,並輸出I am child,PID=29196
由於父進程29195還沒結束,也沒有調用waitpid函數來清除它的子進程,所以子
進程29196顯示爲zombie進程,
此時孫子進程29197,他的父進程29196已經是zombie進程,所以由init 1收納它並
成爲它新的父進程,這也是fork()兩次來避免zombie進程的原理,讓子進程fork後
立即退出,交由孫子進程執行任務,孫子進程的父進程將變成變成init 1,孫子進
程運行結束後init 1會清除孫子進程.
[root@demo ~]# ps -al
F S UID PID PPID C PRI NI ADDR SZ WCHAN TTY TIME CMD
0 S 0 29195 5701 0 77 0 - 379 - pts/4 00:00:00 fork1
1 Z 0 29196 29195 0 78 0 - 0 exit pts/4 00:00:00 fork <defunct>
1 S 0 29197 1 0 78 0 - 378 - pts/4 00:00:00 fork1
4 R 0 29217 16372 0 77 0 - 1050 - pts/1 00:00:00 ps
4 S 0 29507 21039 0 77 0 - 1222 wait pts/2 00:00:00 su
4 S 508 29508 29507 0 75 0 - 1132 - pts/2 00:00:00 bash
3.30s後孫子進程29197結束,父進程還需要再運行20s
[root@demo ~]# ps -al
F S UID PID PPID C PRI NI ADDR SZ WCHAN TTY TIME CMD
0 S 0 29195 5701 0 77 0 - 379 - pts/4 00:00:00 fork1
1 Z 0 29196 29195 0 78 0 - 0 exit pts/4 00:00:00 fork <defunct>
4 R 0 29267 16372 0 77 0 - 1051 - pts/1 00:00:00 ps
4 S 0 29507 21039 0 77 0 - 1222 wait pts/2 00:00:00 su
4 S 508 29508 29507 0 75 0 - 1132 - pts/2 00:00:00 bash
4.孫子進程結束後的20s,也就是從執行腳本開始50s後父進程29195結束,
子進程29196也結束
[root@demo ~]# ps -al
F S UID PID PPID C PRI NI ADDR SZ WCHAN TTY TIME CMD
4 R 0 29304 16372 0 77 0 - 1042 - pts/1 00:00:00 ps
4 S 0 29507 21039 0 77 0 - 1222 wait pts/2 00:00:00 su
4 S 508 29508 29507 0 75 0 - 1132 - pts/2 00:00:00 bash