使用fork()和pipe()的并行子进程:错误的文件描述符和不可预测的行为

我尝试在进程而不是线程中设置并行计算。我从一个非常简单的示例开始:将一个整数从父进程发送到子进程。它起作用了,这是函数processParallel1()的代码:

//parent sends integer to child
bool processParallel1()
{
    //define pipe
    int parent2Child[2];

    //create pipe
    pipe(parent2Child);

    //fork
    pid_t child = fork();

    if(child == 0) //child process
    {
        //close not needed end of pipe
        close(parent2Child[1]);

        for(;;)
        {
            struct pollfd pfd;
            pfd.fd = parent2Child[0];
            pfd.events = POLLIN;

            //wait until data is available at the pipe
            if(poll(&pfd, 1, -1) < 0)
            {
                cout << strerror(errno) << endl;
                return false;
            }

            if((pfd.revents&POLLIN) == POLLIN)
            {
                int data;
                if(!readData1(parent2Child[0], data))
                    return false;

                cout << "c: received data: " << strerror(errno) << endl;

                cout << "data received: " << data << endl;

                if(data == -1)
                    break;
            }
        }

        exit(0);
    }
    else //parent process
    {
        //close not needed end of pipe
        close(parent2Child[0]);

        //send data to child
        if(!writeData1(parent2Child[1], 136758))
            return false;

        cout << "p: wrote data: " << strerror(errno) << endl;

        //send stop data
        if(!writeData1(parent2Child[1], -1))
            return false;

        cout << "p: wrote data: " << strerror(errno) << endl;

        //wait for child to end
        wait(nullptr);

        //close all pipes
        close(parent2Child[0]);
        close(parent2Child[1]);
    }

    return true;
}

在processParallel1()中,我使用以下方法对管道进行写入和读取:

bool writeData1(int fd, const int data)
{
    int bytesWritten = write(fd, &data, sizeof(int));
    if(bytesWritten < 0)
    {
        cout << strerror(errno) << endl;
        return false;
    }
    return true;
}

bool readData1(int fd, int & data)
{
    char intBuf[sizeof(int)];
    int bytesRead = read(fd, intBuf, sizeof(int));
    if(bytesRead > 0)
    {
        data = *(int *)intBuf;
    }
    else if(bytesRead < 0)
    {
        cout << strerror(errno) << endl;
        return false;
    }
    return true;
}

一切正常。现在,我添加了更多数据,结果变得很奇怪。我只交换了用于读写的方法(并创建了新版本的方法,现在名为processParallel3()):

bool writeData3(int fd, const int number, const std::string text)
{
    int bytesWritten = write(fd, &number, sizeof(int));
    if(bytesWritten < 0)
    {
        cout << strerror(errno) << endl;
        return false;
    }

    int size = text.size() + 1;
    bytesWritten = write(fd, &size, sizeof(int));
    if(bytesWritten < 0)
    {
        cout << strerror(errno) << endl;
        return false;
    }

    bytesWritten = write(fd, text.c_str(), size);
    if(bytesWritten < 0)
    {
        cout << strerror(errno) << endl;
        return false;
    }

    return true;
}

bool readData3(int fd, int & number, std::string & text)
{
    char numberBuf[sizeof(int)];
    int bytesRead = read(fd, numberBuf, sizeof(int));
    if(bytesRead > 0)
    {
        number = *(int *)numberBuf;
    }
    else if(bytesRead < 0)
    {
        cout << strerror(errno) << endl;
        return false;
    }

    char sizeBuf[sizeof(int)];
    int size = -1;
    bytesRead = read(fd, sizeBuf, sizeof(int));
    if(bytesRead > 0)
    {
        size = *(int *)sizeBuf;
    }
    else if(bytesRead < 0)
    {
        cout << strerror(errno) << endl;
        return false;
    }

    char textBuf[size];
    bytesRead = read(fd, textBuf, size);
    if(bytesRead > 0)
    {
        text = std::string(textBuf);
    }
    else if(bytesRead < 0)
    {
        cout << strerror(errno) << endl;
        return false;
    }
    return true;
}

当我在主程序中运行进程Parallel()时,在写入和读取后会获得3倍的“成功”,但是在子级中打印接收到的数据后,方法将挂起。

当我添加要在1中的processParallel3()之前直接运行的方法processParallel1()时,一切都很好,但是现在我得到了3次“错误的文件描述符”,它再次挂起。

知道会发生什么或我可以进行哪些进一步的测试?

评论