2012-11-04 76 views
0

我之前發佈了一條關於using fork() and pipes in C 的問題。我稍微改變了一下設計,以便它讀取一個普通的txt文件並對文件中的單詞進行排序。到目前爲止,這是我想出了:C中的多進程,叉和管道

for (i = 0; i < numberOfProcesses; ++i) { 
    // Create the pipe 
    if (pipe(fd[i]) < 0) { 
     perror("pipe error"); 
     exit(1); 
    } 

    // fork the child 
    pids[i] = fork(); 
    if (pids[i] < 0) { 
     perror("fork error"); 
    } else if (pids[i] > 0) {  
     // Close reading end in parent 
     close(fd[i][0]); 

    } else {  
     // Close writing end in the child 
     close(fd[i][1]); 

     int k = 0; 
     char word[30]; 

     // Read the word from the pipe 
     read(fd[i][0], word, sizeof(word)); 

     printf("[%s]", word); <---- **This is for debugging purpose** 

    // TODO: Sort the lists 
    } 
    } 


    // Open the file, and feed the words to the processes 
    file_to_read = fopen(fileName, "rd"); 

    char read_word[30]; 
    child = 0; 

    while(!feof(file_to_read)){ 
    // Read each word and send it to the child 
    fscanf(file_to_read," %s",read_word); 

    write(fd[child][1], read_word, strlen(read_word)); 
    ++child; 
    if(child >= numberOfProcesses){ 
     child = 0; 
    } 
    } 

其中numberOfProcesses是一個命令行參數。所以它所做的是讀取文件中的每個單詞並將其發送給進程。但是,這不起作用。當我在子進程中打印該單詞時,它不會給我正確的輸出。我正在向管道正確寫入/讀取單詞嗎?

回答

1

單詞是按錯誤順序打印還是交錯打印?問題在於,當您向管道寫入單詞時,您期望處理該管道的進程立即安排並打印該單詞。然後你期望主進程再次運行,下一個字被寫入下一個管道等。

但是這並不保證會發生。在安排任何其他進程之前,您的主循環可能會將所有單詞寫入所有管道。這些進程可能不會按照您期望的順序進行安排。 printf調用可能會互相干擾,以使它們的輸出變爲交錯。

如果你真的想要做的事情,那麼posix線程會更好。如果你只是想學習一些關於使用多個進程的知識,那麼我猜你有:-)

+0

我強烈懷疑這是主要問題 - 您絕對需要同步您的併發進程,否則輸出將相互「交錯」(即「混亂」)。 – paulsm4

+0

這是一個任務。我對C編程和在Linux環境下工作都很陌生。所以是的,我必須用流程來做到這一點。用C#寫這個不到2個小時。但請注意,我使用Emacs作爲編輯器,而不是Visual Studio,因此整個調試過程是一場噩夢。 – PoweredByOrange

+0

@ programmer93如果您習慣於IDE,那麼您最好使用Eclipse和CDT。 –

1

在父親中,您寫入strlen()個字節,可能少於30個字節。然而,在孩子中,你總是試着讀取30個字節。您還必須NUL終止該單詞,否則您可能會在您的printf()聲明中看到垃圾或失控的字符串。

在孩子,你必須解析和分割字邊界的輸入或使用stdio作爲@JonathanLeffler建議。當你使用stdio時,你可以免費獲得所有的緩衝和單詞閱讀。

int n; 
char word[31]; 

/* Read the word from the pipe */ 
n = read(fd[i][0], word, sizeof(word) - 1); 
if (n == -1) { 
    perror("read"); 
    /* do error handling */ 
} else { 
    word[n] = 0; 
    printf("[%s]", word); 
} 
+0

你是什麼意思「解析和分割輸入在字邊界」? – PoweredByOrange

+0

您必須在輸入緩衝區(單詞)中查找空白處並在那裏分割字符串。然後保留剩下的字節作爲下一個單詞的輸入。另請注意,讀取可能會返回30個字節或更少,因此請檢查返回值。 –

+0

嗯,我沒有在我的輸入中得到任何空格。例如,這是我的文本文件: '你好,這是一個示例文本文件 這個文件有三條線 這是第三line' 但是當我運行該程序,輸出爲3個流程就像是這個: ''你好,你好嗎? – PoweredByOrange