2012-02-09 114 views
0

我正在尝试连接父级和子级之间的管道。孩子们正在排斥sort,并对他们从父母收到的输入进行排序。孩子们然后写一个单独的管道。每个过程有两个管道。因此父母可以向孩子发送输入。另一个父母可能会收到排序的结果。在C++中使用管道()的管道管道

到目前为止,我的问题一直在阅读输入。我已经从fputs()获得确认,我正在成功写入孩子的输入。之后,我fflush(NULL)并尝试读取孩子的输出。读取的块,因为它永远不会返回或达到fputs后的声明。这很奇怪,因为我相信我已将读数设置为O_NONBLOCK。输出如下所示。

line 174 
line 176 
line 178 

下面是一个代码片段:

int sort_writes[num_sort][2]; 
    int sort_reads[num_sort][2]; 
    int i; 
    int *status; 
    int flags; 
    char buffer[BUFFER_SIZE]; 
    // this should contain a bunch of write fds wrapped in fdopen 
    FILE* to_sort[num_sort]; 
    // the same except with reads 
    FILE* from_sort[num_sort]; 
    //this only include for simplicity and so that exec will happen proper 
    char *sort_argv[2]; 
    sort_argv[0]=(char*)"sort"; 
    sort_argv[1]= (char *)NULL; 

    // This will create all of the pipes for the sorts. 
    // The parent will read 0 and the even pipes. it will write to the odd. 
    for(i=0; i< num_sort; i++){ 
      //parent reads from this pipe. child writes to it. 
        assert(pipe(sort_writes[i]) == 0); 

      //parent write to this pipe. child reads from it. 
        assert(pipe(sort_reads[i]) ==0); 
        switch(fork()){ 
          case 0: //this is the child 
            //this closes unnecessary fds 
            _close_less_than(i, sort_writes); 
            _close_less_than(i, sort_reads); 
            dup2(sort_reads[i][0], STDIN_FILENO); 
            // standard out becomes parent pipe in 
            dup2(sort_writes[i][1], STDOUT_FILENO); 
                            execv(SORT_LOC.c_str(), sort_argv); 
          default: // this the parent. 
            //clean up. close unused. 
            close(sort_writes[i][1]); 
            close(sort_reads[i][0]); 
        } 

    } 
    //Creates a file pointer for all of the fds I will use to communicate with my sorts 
    //It also sets all reads to nonblock and the parent write stdio buffers to zero.   
    for(i=0; i< num_sort; i++){ 
      assert((from_sort[i]= fdopen(sort_writes[i][0] ,"r")) != NULL); 
      assert((to_sort[i]= fdopen(sort_reads[i][1] , "w")) != NULL);   //pipes ignore truncate 

      flags = fcntl(sort_writes[i][0], F_GETFL); 
      flags |= O_NONBLOCK; 
      fcntl(sort_writes[i][0], F_SETFL, flags); 


    } 

    for(i=0; i<(int)theArray.size(); i++){ 
      fputs(theArray.back().c_str(), to_sort[i % num_sort]); 
      theArray.pop_back(); 
      fflush(NULL); // so that the data gets from stdio buffers to pipe buffers.  
    } 
    cout << "line 174 \n"; 
    for(i=0; i <1; i++){ 
      cout << "line 176 \n"; 
      while(!feof(from_sort[i])){ 
        cout << "line 178 \n"; 
        cout << fgets(buffer, BUFFER_SIZE, from_sort[i]); 
        cout << buffer; 
        cout << "at least i tried \n"; 
      } 
+0

整个'dup2()'和'close()'问题比起初看起来更复杂。参见[病理病例详细讨论](http://www.unixwiz.net/techtips/remap-pipe-fds.html)和[完整示例代码](http://www.unixwiz.net/techtips/remap -pipe-fds.c.txt)。 – 2012-02-10 03:25:07

回答

2

exec之前忘了dup2close。通过你的代码,sort不知道要使用哪个文件描述符。我不知道_close_less_than是做什么的,但是如果它关闭了描述符0,1或2,那么你就会打电话给sort带有一个它无法理解的环境。你必须将你的管道连接到孩子的stdin和stdout。

+0

我很抱歉浪费你的时间。我在复制时意外地忽略了我的代码行。 close小于函数是函数,它遍历并关闭数组中的所有fds,索引小于传递的int。再次感谢你的时间。关于dup2,我相信我正在做的事情对于手册是有意义的。我想用适当的管道替换标准输入和输出是吗? – order 2012-02-10 03:14:42

+0

是的。尽管你的示例代码仍然缺少close函数。在'dup2'调用之后,您需要关闭两个管道的两端。 (当然,不要关闭重复的描述符。)另外,如果某些程序没有有效的“stderr”,它们将不起作用。如果需要,你可以打开''/ dev/null'。 – 2012-02-10 03:17:00

+0

再次感谢。我想我终于知道为什么我的所有管道都失败了。我应该从数组中获取文件描述符,孩子们的标准指向相同的文件描述。我将确保用NULL替换我的标准错误。再次感谢那么多人。我花了很多时间才意识到这一点。 – order 2012-02-10 03:54:46