如何 fork n 個進程(n > 2)

原文地址:

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  


發佈了28 篇原創文章 · 獲贊 9 · 訪問量 25萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章