2012-07-11 33 views
1

我有一個任務是從命令行中取出一個字符串,並使用fork()將其逆轉並在單獨的子進程中輸出每個字符。我只是沒有從fork()調用獲取正確的輸出。問題是索引在輸出上混亂了,比如3,1,2,0,當它應該是3,2,1,0 ...等等......什麼讓它更容易混淆,它是隨機成功的單詞長度爲3個字符(但不總是),但對於4個字符以上的單詞而言,通常不正確。沒有fork()調用,循環正常工作。使用fork()爲每個孩子輸出1個數組元素,C++

這是我的主要功能,問題存在於for循環中。

int main(int argc, char **argv){ 
    pid_t childpid = 0; 
    int i; 
    char* invert = new char[strlen(argv[1])+1]; 
    int invert_length = strlen(argv[1]); 
    strcpy(invert, argv[1]); 
    for(i=invert_length-1; i>=0; i--){ 
     childpid = fork(); 
     if(childpid==(pid_t) 0){ 
      //I am the child    
      cout<<"Child ["<< i <<"] = " << invert[i] <<"."<<endl; 
      break; 
     } 
    } 
    return 0; 
} 

回答

2

程序的簡單修改使得它的工作。讓孩子做下一個叉子。每個進程都等待它產生的進程。

int main(int argc, char **argv){ 
    pid_t childpid = 0; 
    int i; 
    char* invert = new char[strlen(argv[1])+1]; 
    int invert_length = strlen(argv[1]); 
    strcpy(invert, argv[1]); 
    for(i=invert_length-1; i>=0; i--){ 
     childpid = fork(); 
     if(childpid==(pid_t) 0){ 
      //I am the child 
      cout<<"Child ["<< i <<"] = " << invert[i] <<"."<<endl; 
      continue; 
     } 
     break; 
    } 
    wait(0); 
    return 0; 
} 

編輯: Skizz反對,認爲每個進程啓動下一個之前執行的工作。在問題中沒有要求所有的流程都是首先推出的,但下面的版本是這樣做的。

int main(int argc, char **argv){ 
    pid_t childpid = 0; 
    int i; 
    char* invert = new char[strlen(argv[1])+1]; 
    int invert_length = strlen(argv[1]); 
    strcpy(invert, argv[1]); 
    for(i=0; i<invert_length; ++i){ 
     childpid = fork(); 
     if(childpid!=(pid_t) 0){ 
      wait(0); 
      break; 
     } 
    } 
    if (i-->0) cout<<"Child ["<< i <<"] = " << invert[i] <<"." <<endl; 
    return 0; 
} 
+0

非常感謝!我正準備在使用睡眠(5 /(i + 1))方法後才能註銷,並且每次都有效地計時,但是看到了您的帖子並認爲這樣會更好。 – Nibirue 2012-07-11 11:05:09

+0

儘管這確實解決了原始問題,但它實際上是一個單一的流程解決方案。每個新進程在前一個進程完成時創建。如果我是一位設置這個問題的老師,我可能會因此失敗,因爲中心概念是協調併發進程而不是如何對它們進行序列化。對它們進行串行化使得使用多個進程的整個過程失敗。 – Skizz 2012-07-11 15:57:55

+0

@Skizz:任何形式的協調都可以有效地序列化它們。考慮到問題的參數,我提出的解決方案是最有效的方法。 Regards – jxh 2012-07-11 16:03:51

0

這和pthreads一樣。沒有保證,這些孩子將按照產卵的順序執行。心智SIGCHLD。

0

問題是fork調用產生一個新進程,複製調用進程。正如你在一個循環內部做的那樣,你現在有很多進程都想同時執行。它們執行的順序(因爲CPU一次只能執行一個進程*)取決於操作系統,因爲這是選擇執行哪個進程的事情,所以輸出變得不確定。

爲了解決這個問題,每個產生的進程都需要知道何時輸出使用進程之間某種類型的同步的手段。

注:

  • 我忽略了超線程/多內核的簡單性。
0

編輯:

你可以叉,然後調用wait,從而滿足硬件需求。 我原來下面的答案是你如何能在更復雜的環境(一個真正的應用程序)運行這個和上面

指出你將如何能夠採取從運行一些代碼,在一個單獨的進程

添加wait優勢

int main(int argc, char **argv){ 
    pid_t childpid = 0; 
    int i; 
    char* invert = new char[strlen(argv[1])+1]; 
    int invert_length = strlen(argv[1]); 
    strcpy(invert, argv[1]); 
    for(i=invert_length-1; i>=0; i--){ 
     childpid = fork(); 
     if(childpid==(pid_t) 0){ 
      //I am the child    
      cout<<"Child ["<< i <<"] = " << invert[i] <<"."<<endl; 
      break; 
     } 
     else { 
      int stat; 
       wait(&stat); 
     } 
    } 
    return 0; 
} 

我同意@illusionoflife,但如果它的功課,那麼它必須能夠

你可以設置一個事件處理程序(例如用libevent的)爲SIGCHLD,然後啓動下一子AFTE r接收到第一個SIGGCHLD等

此練習的要點可能不是跨多個CPU的負載均衡,而是顯示您可以使用Copy On Write執行的操作。

Here是我提出的問題在幾個月前,讓你開始

相關問題