0

我之前发布了一个关于在 C 中使用 fork() 和管道的问题 。我稍微改变了设计,让它读取一个常规的 txt 文件并对文件中的单词进行排序。到目前为止,这是我想出的:

 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;
    }
  }

wherenumberOfProcesses是一个命令行参数。所以它的作用是读取文件中的每个单词并将其发送到一个进程。然而,这不起作用。当我在子进程中打印单词时,它没有给我正确的输出。我是否正确地从管道中写入/读取单词?

4

2 回答 2

1

在父级中,您写入strlen()可能小于 30 个字节的字节。但是,在孩子中,您总是尝试读取 30 个字节。您还必须以 NUL 终止单词,否则您可能会在printf()语句中看到垃圾或失控的字符串。

在孩子中,您必须在单词边界解析和拆分输入,或者按照@JonathanLeffler 的建议使用 stdio。当您使用 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);
}
于 2012-11-04T21:56:26.150 回答
1

单词是否以错误的顺序打印或交错?问题是,当您向管道写入一个单词时,您期望处理该管道的进程立即被调度并打印该单词。然后您希望主进程再次运行,并将下一个单词写入下一个管道等。

但这并不保证会发生。您的主循环可能会在安排任何其他进程之前将所有单词写入所有管道。这些过程可能不会按照您期望的顺序安排。并且 printf 调用可能会相互干扰,从而使它们的输出交错。

如果你真的想做你想做的事,那么 Posix 线程会更好。如果您只是想了解有关使用多个进程的知识,那么我想您已经 :-)

于 2012-11-04T22:10:24.773 回答