2017-01-05 2 views
1

Я пытаюсь сделать двунаправленную трубу, чтобы сделать родительский процесс отправки сообщения на процесс ребенка и ждать его ответа, сделать что-то с ответ и отправьте другое сообщение, и повторите это снова и снова.
ребенка процесса использует STDIN и STDOUT для приема и отправки ввода и родительского использовать сообщения как C++ строка, поэтому они преобразуются перед отправкой и после получения, а также различные сообщения имеют разные (неизвестно) длины.
Я написал простой код, чтобы иллюстрировать:
C++ двунаправленной трубы - застряла пытается читать из дочернего процесса в цикле

Parent.cpp:

#include <unistd.h> 
#include <iostream> 
#include <cstring> 
#include <string> 

int main(){ 
    int parent_to_child[2]; 
    int child_to_parent[2]; 

    pipe(parent_to_child); 
    pipe(child_to_parent); 

    int childPID = fork(); 

    if(childPID == 0){ 
     //this is child 
     close(parent_to_child[1]);//Close the writing end of the incoming pipe 
     close(child_to_parent[0]);//Close the reading end of the outgoing pipe 

     dup2(parent_to_child[0], STDIN_FILENO);//replace stdin with incoming pipe 
     dup2(child_to_parent[1], STDOUT_FILENO);//replace stdout with outgoing pipe 

     //exec child process 
     char filename[] = "child.out"; 
     char *newargv[] = { NULL }; 
     char *newenviron[] = { NULL }; 
     execve(filename, newargv, newenviron); 
    }else{ 
     //this is parent 
     close(parent_to_child[0]);//Close the reading end of the outgoing pipe. 
     close(child_to_parent[1]);//Close the writing side of the incoming pipe. 

     int parent_frame = 0; 
     char str_to_write[100]; 

     char reading_buffer; 
     std::string received_str; 

     do{ 
      //Make the frame number a cstring and append '\n' 
      strcpy(str_to_write, std::to_string(parent_frame).c_str()); 
      strcat(str_to_write,"\n"); 

      write(parent_to_child[1], str_to_write, strlen(str_to_write)); 
      std::cout << "Parent sent: "<< str_to_write <<std::endl; 


      received_str = ""; 
      while(read(child_to_parent[0], &reading_buffer, 1) > 0){ 
       received_str += reading_buffer; 
      } 

      std::cout << "Parent received: "<< received_str<< std::endl; 
     } while (++parent_frame); 
    } 
    return 0; 
} 

Child.cpp

#include <unistd.h> 
#include <iostream> 

int main(){ 
    int child_frame = 0; 
    char child_buffer[1024]; 
    do{ 
     std::cin >> child_buffer; //wait for father's messages 
     std::cout << "CHILD received: "<< child_buffer<<" at frame "<< child_frame<<"\n"; //return message to father 
    }while(++child_frame); 

    return 0; 
} 

-исполнители Родительские выходы:

Parent sent: 0 

... И застревает

Если я не делаю трубу от ребенка к родителю и пусть родительская запись в STDOUT код работает как spected, как я вижу ответы ребенка в терминале , Таким образом, указывая, что ребенок может читать от родителя, но по какой-то причине родитель не может читать от ребенка.

Так что мой вопрос: почему родитель не может прочитать выход ребенка и как это может работать? что я делаю неправильно?

ответ

0

Проблема заключается в вызове родителя к read(2) внутри самого внутреннего цикла while.

Это постоянное считывание данных до тех пор, пока read(2) не вернет значение < = 0. Но это происходит только тогда, когда (1) возникает ошибка или (2) ребенок закрывает свой конец записи. Таким образом, ребенок отправляет свое сообщение, которое родитель счастливо читает, а затем просто сидит в ожидании дальнейших данных от ребенка. Который, очевидно, никогда не прибывает.

Проблема заключается в вашем состоянии во время цикла. Вы не хотите читать до EOF или ошибки, вы хотите прочитать полную строку (если вы используете новые строки как разделители сообщений). Посмотрите на getline(3), чтобы сделать это немного проще, и избегайте чтения одиночных байтов за раз, или std::getline, если вы превратите код в более стиль C++.

Смежные вопросы