原文地址:
http://kenby.iteye.com/blog/1165923
講到fork, 一個經典的例子如下:
if ((pid = fork()) == 0) {
printf("in child %d\n", getpid());
} else if (pid > 0) {
printf("in parent\n");
} else {
perror("fork");
exit(0);
}
現在, 我要創建5個進程, 每個進程都打印出自己的pid, 寫下如下代碼:
#include <stdio.h>
#include <stdlib.h>
#define N_PROCESS 5
int main()
{
pid_t pid[N_PROCESS];
int i;
/* create child process */
for (i = 0; i < N_PROCESS; i++) {
if ((pid[i] = fork()) == 0) {
printf("in child %d\n", getpid());
} else if (pid[i] > 0) {
printf("in parent\n");
}
}
return 0;
}
看似沒有問題, 編譯運行, 結果令人驚訝:
in parent
in parent
in parent
in parent
in parent
in child 11799
in parent
in parent
in parent
in parent
in child 11799
in parent
in parent
in parent
in child 11807
in parent
in parent
in parent
in child 11803
in parent
in parent
in parent
in parent
in parent
in child 11805
in child 11799
in parent
in child 11804
in parent
in parent
in child 11799
in parent
in parent
in child 11806
in child 11808
in parent
in parent
in parent
in child 11803
in child 11809
in parent
in parent
in child 11802
in parent
in parent
in child 11799
in child 11801
in parent
in parent
in parent
in child 11799
in parent
in child 11804
in parent
in child 11811
in child 11799
in child 11801
in parent
in child 11815
in parent
in parent
in parent
in child 11802
in child 11812
in parent
in child 11799
in child 11801
in child 11813
in parent
in parent
in parent
in child 11800
in parent
in parent
in parent
in child 11799
in parent
in child 11804
in child 11810
in child 11817
in parent
in parent
in child 11802
in child 11812
in child 11819
in child 11799
in child 11801
in parent
in parent
in child 11816
in parent
in parent
in child 11802
in parent
in child 11814
in child 11799
in child 11801
in parent
in child 11815
in child 11818
in parent
in child 11800
in parent
in child 11822
in parent
in parent
in child 11800
in parent
in parent
in child 11824
in child 11799
in child 11801
in child 11813
in parent
in child 11823
in parent
in child 11800
in child 11820
in parent
in parent
in parent
in child 11800
in parent
in child 11822
in child 11825
in child 11799
in child 11801
in child 11813
in child 11821
in parent
in parent
in child 11800
in child 11820
in parent
in child 11828
in child 11799
in child 11801
in child 11813
in child 11821
in child 11826
in parent
in child 11800
in child 11820
in child 11827
in child 11829
數一數, 程序創建了31個子進程! 怪哉, 哪裏出問題了呢?
仔細分析一下, 第一次fork調用時, i = 0, fork完成後, 子進程和父進程擁有相同的存儲,
即兩者的 i = 0,然後父進程執行parent代碼段, 打印 "in parent", 子進程執行child代碼
段, 打印自己的pid. 關鍵是, 到了這裏, 子進程沒有退出, 處於for循環中, 於是子進程接着
執行 i = 1 時的for循環, 子進程執行fork, 又創建子進程, 這樣就產生孫子進程. 按照這種
步驟, 孫子進程又會創建子進程....稍微分析一下, 可以得到遞推公式,如果想創建n個子進程,
將執行 2^n - 1次fork調用併產生2^n-1個子進程, 真是子子孫孫無窮盡也...
可見, 問題的關鍵是, 終止子進程繼續執行for循環, 修改代碼:
#include <stdio.h>
#include <stdlib.h>
#define N_PROCESS 5
int main()
{
pid_t pid[N_PROCESS];
int i;
/* create child process */
for (i = 0; i < N_PROCESS; i++) {
if ((pid[i] = fork()) == 0) {
printf("in child %d\n", getpid());
exit(0); /* 讓子進程退出 */
} else if (pid[i] > 0) {
printf("in parent\n");
}
}
return 0;
}
運行結果如下:
in parent
in child 12037
in parent
in parent
in child 12039
in child 12038
in parent
in child 12040
in parent
in child 12041
這次只創建了5個進程, 但parent代碼段執行了5次, 不符合我們的要求, 再改:
#include <stdio.h>
#include <stdlib.h>
#define N_PROCESS 5
int main()
{
pid_t pid[N_PROCESS];
int i;
/* create child process */
for (i = 0; i < N_PROCESS; i++) {
if ((pid[i] = fork()) == 0) {
printf("in child %d\n", getpid());
exit(0); /* 讓子進程退出 */
}
}
printf("in parent\n");
return 0;
}
運行結果如下:
in child 12072
in parent
in child 12074
in child 12075
in child 12073
in child 12076