【问题标题】:C reading all data from pipeC从管道中读取所有数据
【发布时间】: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。

标签: c pipe fork child-process


【解决方案1】:

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

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

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

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

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

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-04-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-30
    相关资源
    最近更新 更多