2014-09-24 81 views
1

我正在学习如何使用C管道,而且我在编写一个字符串列表一个接一个地写入子进程的管道时遇到了一些困难,然后在父进程中从管道读取它们。这里是我当前的代码:使用管道读取字符串数组C使用C

#include <stdio.h> 
#include <stdlib.h> 
#include <sys/types.h> 
#include <unistd.h> 
#include <sys/wait.h> 
#include <string.h> 

int main() 
{ 
    int pfd[2]; 
    char buf[1000]; 
    int cfork; 

    if (pipe(pfd) == -1) { 
     exit(1); 
    } 

    cfork = fork(); 

    if (cfork == -1) { 
     printf("Fork Failed\n"); 
     exit(1); 
    } 
    else if (cfork == 0) { 
     printf("Child Process\n"); 

     char *fruit[] = { 
      "Orange", "Apple", 
      "Banana", "Pear" 
     }; 

     int num_fruit = 4; 
     for (int i = 0; i < num_fruit; i++) { 
      printf("Current fruit: %s\n", fruit[i]); 
      write(pfd[1], fruit[i], (strlen(fruit[i]))); 
     } 
     _exit(0); 
    } 
    else { 
     printf("Parent Process\n"); 
     read(pfd[0], buf, sizeof(buf)); 
     printf("Fruit Fetched: %s\n", buf); 
     wait(NULL); 
    } 

    return 0; 

} 

我所要做的,就是在孩子读水果串,将其写入管道,并有家长读这个字符串并打印出来,直到所有的字符串已被打印。我的麻烦是,孩子,因为它在一个循环,只是不断添加每个字符串到缓冲区,所以程序,现在,打印出“OrangeAppleBanana”。我很确定我也需要在父级循环,但是当我尝试了一个等待子节点发送的一些结束条件字符串(例如“完成”)的while循环时,我的程序仍然卡在无限循环。

对于刚接触C的人来说,最简单的方法是一个接一个地在子项中写入字符串,并让父进程一个接一个地打印出来?

编辑

#include <stdio.h> 
#include <stdlib.h> 
#include <sys/types.h> 
#include <unistd.h> 
#include <sys/wait.h> 
#include <string.h> 

int main() 
{ 
    int pfd[2]; 
    int cfork; 

    if (pipe(pfd) == -1) { 
     exit(1); 
    } 

    cfork = fork(); 

    if (cfork == -1) { 
     printf("Fork Failed\n"); 
     exit(1); 
    } 
    else if (cfork == 0) { 

     int numbers[] = { 
      1, 2, 
      3, 4 
     }; 

     int limit = 4; 
     close(pfd[0]); 
     for (int i = 0; i < limit; i++) { 
      printf("Child - Current Number: %d\n", numbers[i]); 
      write(pfd[1], &numbers[i], sizeof(numbers[i])); 
     } 
     close(pfd[1]); 
     _exit(0); 
    } 
    else { 

     int temp; 
     int reads = 4; 
     close(pfd[1]); 
     for (int i = 0; i < reads; i++) { 
      read(pfd[0], &temp, sizeof(temp)); 
      printf("Parent - Number Fetched: %d\n", temp); 
     } 
     close(pfd[0]); 
     waitpid(-1, NULL, 0); 
    } 

    return 0; 

这是我的新代码,在那里我使用整数而不是字符串。似乎工作到目前为止。仍然不确定我在做什么错误的字符串。

回答

0
//Child 
close(pfd[0]); // Close read end this blocks if parent is reading from pipe 
write(pfd[1]...); // write data into pipe 
close(pfd[1]); // close write end of pipe now the pipe is ready to read 

// Parent 
close(pfd[1]); // close write end of pipe blocks if child is writing to pipe. 
read(pfd[0] ...); 
close(pfd[0]..); // close read end so pipe is ready to write to. 
1

我相信你的问题是与“字符串”。 C中的字符串以null结尾,所以当你通过管道发送它们时,receiver(parent)不知道字符串结束的位置。 Strlen确实计算了一个字符串中的字符数,但不包括空字符。你应该这样做:

write(pfd[1], fruit[i], (strlen(fruit[i]))+1); 

家长现在可以知道何时何地拆分你的字符串。

另一个问题是,您还需要在parrent中循环。你需要在循环中设置一个条件来检查EOF。在你的例子中,你知道你会得到4个水果,你可以循环4次。

关闭不需要的管道读写端部是一个很好的做法。在你的例子中,孩子应该关闭阅读结束,而父母应该关闭写作结束。你可以这样做:

close(pfd[0]); //use this in child 

close(pfd[1]); //use this in parent 

你也应该习惯关闭所有你不需要的描述符。在你的例子中,在完成写/读操作之后,你应该关闭子进程和父进程的管道。这样,您可以创建一个读取循环条件,在EOF之后关闭。 (当孩子关闭管道,接收器可以结束)

作为一个额外的小费,尝试错误与“PERROR” http://www.tutorialspoint.com/c_standard_library/c_function_perror.htm

+0

报告我应该把close()方法的每个相应回路内部或外部的语句?我按照你的建议改变了strlen(),为父循环做了另一个循环来循环和读取pipe,并且把两个close()语句放在循环之外。仍然没有得到正确的输出。此外,我有点困惑,如果和在哪里,我应该添加一个wait()或waitpid()父。在循环?外?我已经尝试了两种,但我一定是做错了。 – SherMM 2014-09-24 15:12:44

+0

我现在不在家里的电脑上,所以我无法测试你的解决方案是否有效。我会尽快回家。 您应该在您的子进程中关闭pfd [0],并关闭父进程中的pfd [1]。在你成功分叉后,你不得不关闭它们一次,而不是循环。你能告诉我你得到了什么样的输出?也许写你写的新循环,所以我可以看到代码? 我会在几个小时内发布一个工作解决方案,当我回到家时,我可以自己测试它。 – IamSneaky 2014-09-25 07:11:58

+0

现在对我来说同样的情况。有机会的时候我会发布代码。我运行它只是一个整数列表,而不是原来的水果列表,它的工作。我认为这可能与正在阅读的字符串有关系 – SherMM 2014-09-25 13:51:33