2012-11-04 38 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