C ++双向管道 - 试图在循环中读取子进程

时间:2017-01-05 21:42:27

标签: c++ c++11 pipe c++14 ipc

我正在尝试制作一个双向管道,让进程向进程发送消息并等待其答案,对答案执行某些操作并发送另一条消息,一遍又一遍地重复 进程使用STDIN和STDOUT接收和发送输入,将消息用作 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

......而且卡住了

如果我不从 child到创建管道并让父写入STDOUT,则代码按照指定的方式工作,因为我看到了终端中孩子的响应。因此,表明孩子能够从父母那里读书,但由于某种原因,父母不能从孩子那里读书。

所以我的问题是:为什么父母无法读取子输出,这怎么可行呢?我做错了什么?

1 个答案:

答案 0 :(得分:0)

问题在于父母在最里面的while循环内调用read(2)

这会持续读取数据,直到read(2)返回一个值&lt; = 0.但这只发生在(1)发生错误或(2)子句关闭管道的写入结束时。因此,孩子发送其消息,父母愉快地读取,然后只是等待来自孩子的进一步数据。这显然永远不会到来。

问题是你在while循环中的条件。您不想在EOF或错误之前阅读,您想要读取整行(如果您使用换行符作为消息分隔符)。查看getline(3)以使其更容易并且避免一次读取单个字节,或者std::getline如果将代码转换为更多C ++样式。