C从管道中读取所有数据

Posted

技术标签:

【中文标题】C从管道中读取所有数据【英文标题】:C reading all data from pipe 【发布时间】:2016-10-18 19:45:56 【问题描述】:

我的程序创建子进程并设置管道与它通信。当我尝试从管道读取数据时会出现问题。由于子进程已经结束(我使用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);
    

【问题讨论】:

父进程需要关闭pipe2pr[1]。它正在阻止自己获得 EOF。 【参考方案1】:

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

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

但读取只是冻结并等待更多数据到来。我在这里错过了什么?

几件事。最重要的可能是当一个进程分叉时,父进程的打开文件描述符的子进程副本引用内核底层打开文件表中与父进程相同的条目,每个条目都保持打开状态,直到 all 其上的句柄已关闭。子进程在退出时会关闭其所有文件描述符,但两个管道的两端在父进程中仍保持打开状态,因此不会向读取器发出文件结束信号。每个进程都必须关闭它不使用或已完成使用的管道末端。

另外,你应该先read(),然后wait(),因为如果子进程向管道写入足够多的数据,那么它可能会阻塞,如果父进程直到子进程退出后才读取,那么你将拥有僵局。

此外,我认为没有任何理由将任一管道端复制到父级的标准流上(导致关闭原始流)。只需通过它们的文件描述符来操作管道,就像你已经做了一半一样。如果您想要这些的流接口,请使用fdopen() 获取。

【讨论】:

以上是关于C从管道中读取所有数据的主要内容,如果未能解决你的问题,请参考以下文章

读取管道(C/C++),没有错误,但不是所有数据

从命名管道、C 程序(编写器)和 Python(读取器)获取额外数据

从管道读取()保证在EOF之前提供所有原子写入的数据?

C - 同时从两个管道(来自两个子进程的父进程)读取?

是否应该在刚刚从该 FIFO 读取所有数据之后从 FIFO 块中读取?

C管道写入/读取双打序列失败