C读取管道中的所有数据

时间:2016-10-18 19:45:56

标签: c pipe fork child-process

我的程序创建子进程并设置管道以与之通信。当我尝试从管道中读取数据时,会发生此问题。由于子进程已经结束(我使用wait来确保)EOF应该在数据流的末尾,从而结束读取(如pipe的手册页中所示)。但是read只是冻结并等待更多数据来临。 我在这里缺少什么?

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>



void setfd(int *in, int *out) {
    dup2(out[1], 1);
    dup2(in[0], 0);
}

int main(int argc, char *argv[]) {
    int status;
    int pipe2ch[2], pipe2pr[2];
    char *newargv[] = {NULL, NULL};
    newargv[0] = argv[1];

    pipe(pipe2ch);
    pipe(pipe2pr);

    setfd(pipe2pr, pipe2ch);
    int a;
    if (!(a = fork())) {
        setfd(pipe2ch, pipe2pr);
        execve(newargv[0], newargv, NULL);
        exit(1);
    } else {
        printf("hello!\n");
        fflush(stdout);

        char str;

        wait(&status);
        while (read(pipe2pr[0], &str, 1) > 0) {
            fprintf(stderr, "%c", str);
        }
        exit(0);
    }
}

1 个答案:

答案 0 :(得分:1)

  

由于子进程已经结束(我使用wait来确保),EOF应该在数据流的末尾,从而结束读取(如管道的手册页中那样)。

我不确定你读过什么来暗示这一点。或者也许这是我不理解的措辞。 EOF不是流中的字符。

  

但是读取只是冻结并等待更多数据来。我在这里缺少什么?

有几件事。最重要的一个可能就是当一个进程分叉时,父进程打开文件描述符的子进程副本引用内核的打开文件基础表中的相同条目,就像父进程一样,每个进程都保持打开状态直到 all < / em>上的句柄已关闭。子进程退出时关闭所有文件描述符,但 两个管道的两端在父 中保持打开状态,因此不会向读者发送文件结尾信号。每个过程必须关闭它不使用或完成使用的管道末端。

此外,您应首先read(),然后wait(),如果子进程将足够的数据写入管道然后它可能会阻塞,如果父进程在子进程退出之后才读取你会陷入僵局。

此外,我没有看到任何理由将管道末端欺骗到父级的标准流(导致关闭原始的流)。只需通过文件描述符操作管道,就像你已经完成的那样。如果你想要一个流接口,那么使用fdopen()来获得一个。