使用Write()写入管道始终返回0

时间:2017-02-28 04:57:42

标签: c pipe parent-child

我试图通过以下方式让两个进程相互写入:  1.家长写信给Child  2.孩子从家长收到消息  3.孩子写信给家长  4.家长收到来自孩子的信息

我不明白为什么当我试着发信时#34; A"写函数总是返回零。有谁知道为什么?我查看了手册页,它只是说它返回0字节但是" A"是一个应该是一个字节的字符?

int main()
{
    int fdP[2]; //used for child to contact parent 
    int fdC[2]; //used by parent to contact child
    int nBytes;
    char readBuffer[2];
    char writeBuffer[2];

    pipe(fdP); //Child >> Parent
    pipe(fdC); //Parent >> Child

    pid_t  pid;
    pid = fork();
    if( pid < 0)
    {
        perror("There was an error during the fork");
        exit(1);
    }

    //two processes running here
    if (pid == 0) //child process
    {   
        close(fdP[0]);
        close(fdC[1]);
        while (nBytes != 0) //when nbytes is nonzero it received a message
        {
            nBytes = read(fdP[0], readBuffer, sizeof(readBuffer));
        }
        printf("Child received: %s\n", readBuffer);

        write(fdP[1], "B", sizeof(readBuffer));
        exit(0);
    }
    else //parent process
    {
        close(fdC[1]);
        close(fdP[0]);

        while(write(fdC[1], "A", sizeof("A")) != 0) //THIS ALWAYS RETURNS ZERO
        {
            printf("%s\n", "I'M STUCK HERE");
        }

        while (nBytes != 0) //when nbytes is nonzero it received a message
        {
            nBytes = read(fdC[0], readBuffer, sizeof(readBuffer));
        }
        printf("Parent received: %s\n", readBuffer);
        wait(NULL);
    }
    printf("%s\n", "finished");
}

3 个答案:

答案 0 :(得分:0)

我看到一些问题:

  • 在初始化之前使用nBytes。这是未定义的行为。
  • sizeof("A")错了。这给出了const char*的大小,而不是字符串的实际大小。
  • 使用0测试read()和write()的逻辑是向后的。 (实际上,对于这个玩具程序,你可以完全删除循环和nBytes变量,只需执行一次read()和write()一次。)

此外,您混淆了文件描述符。假设您对它们的评论是正确的,这里是详细信息:

  • 子进程应该从fdC [0]读取,而不是fdP [0]。
  • 父进程将关闭相反的文件描述符。
  • 父进程应从fdP [0]读取,而不是fdC [0]。

当我修复上述所有内容后,您的代码似乎可以执行您想要的操作。这就是我最终的结果:

int main()
{
    int fdP[2]; //used for child to contact parent 
    int fdC[2]; //used by parent to contact child
    char readBuffer[2];

    pipe(fdP); //Child >> Parent
    pipe(fdC); //Parent >> Child

    pid_t  pid;
    pid = fork();
    if( pid < 0)
    {
        perror("There was an error during the fork");
        exit(1);
    }

    //two processes running here
    if (pid == 0) //child process
    {   
        close(fdP[0]);
        close(fdC[1]);
        read(fdC[0], readBuffer, sizeof(readBuffer));
        printf("Child received: %s\n", readBuffer);
        write(fdP[1], "B", 2);
        exit(0);
    }
    else //parent process
    {
        close(fdC[0]);
        close(fdP[1]);
        write(fdC[1], "A", 2);
        read(fdP[0], readBuffer, sizeof(readBuffer));
        printf("Parent received: %s\n", readBuffer);
        wait(NULL);
    }
    printf("%s\n", "finished");
}

答案 1 :(得分:0)

在孩子中,你正在关闭管道的一侧,然后尝试阅读。在父级中,您关闭管道的一侧,然后尝试写入。

此外,while循环没有检查正确的大小。

试试这个:

int main()
{
    int fdChildtoParent[2]; //used for child to contact parent
    int fdParentToChild[2]; //used by parent to contact child
    int nBytes;
    char childInbox[1];
    char parentInbox[1];

    pipe(fdChildtoParent); //Child >> Parent
    pipe(fdParentToChild); //Parent >> Child

    pid_t pid;
    pid = fork();
    if(pid < 0)
    {
        perror("There was an error during the fork");
        exit(1);
    }

    //two processes running here
    if(pid == 0) //child process
    {
        close(fdChildtoParent[0]);
        close(fdParentToChild[1]);

        read(fdParentToChild[0], childInbox, sizeof(childInbox));

        printf("Child received: %s\n", childInbox);

        write(fdChildtoParent[1], "B", sizeof("B"));

        exit(0);
    }
    else //parent process
    {
        close(fdParentToChild[0]);
        close(fdChildtoParent[1]);

        write(fdParentToChild[1], "A", sizeof("A"));

        read(fdChildtoParent[0], parentInbox, sizeof(parentInbox));

        printf("Parent received: %s\n", parentInbox);

        exit(0);
    }
}

答案 2 :(得分:0)

  • 您的代码无效。复制字节的循环应该使用写入中的读取计数,发送“A”的代码实际上发送两个字节,而不是一个,因为sizeof“A”包括尾随空值。

  • 您的评论'当nbytes非零时收到消息'也不正确。如果它是肯定它收到了一个长度的消息,否则你需要打印一个错误,例如,使用perror(),然后你几乎肯定需要关闭套接字

  • 除了最后一个确实返回零的读数外,你忽略了每一个读数,所以你丢失了数据。

正确的阅读方式如下:

while ((count = read(fd, buffer, sizeof buffer)) > 0)
{
    // do something with buffer[0..count], for example write(fd2, buffer, count);
}
if (count == 0)
    ; // end of stream
else
{
    // count < 0
    perror("read");
}