将标准输入重定向到子程序不会使程序终止

问题描述 投票:0回答:1

我一直试图做的是建立一个分叉两个孩子的程序。父级从stdin读取,然后通过管道将其重定向到其子进程。然后,子进程复制管道的读取端,以便可以从stdin(而不是管道)读取管道,然后将其打印到stdout中。这是代码:

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

int main(int argc, char **argv) {
    char buf[100];
    int pipe_one[2];
//    int pipe_two[2];

    pipe(pipe_one);
//    pipe(pipe_two);

    // First child
    switch(fork()) {
        case -1:
            exit(EXIT_FAILURE);
        case 0:
            close(pipe_one[1]);
            dup2(pipe_one[0], STDIN_FILENO);
            close(pipe_one[0]);
            while (fgets(buf, 100, stdin)) {
                fputs(buf, stdout);
            }
            fflush(stdout);
            exit(EXIT_SUCCESS);
        default:
            break;
    }

    // Second child
/*    switch(fork()) {
        case -1:
            exit(EXIT_FAILURE);
        case 0:
            close(pipe_two[1]);
            dup2(pipe_two[0], STDIN_FILENO);
            close(pipe_two[0]);
            while (fgets(buf, 100, stdin)) {
                fputs(buf, stdout);
            }
            fflush(stdout);
            exit(EXIT_SUCCESS);
        default:
            break;
    }*/

    close(pipe_one[0]);
//    close(pipe_two[0]);
    FILE *out_1 = fdopen(pipe_one[1], "w");
//    FILE *out_2 = fdopen(pipe_two[1], "w");

    while (fgets(buf, 100, stdin)) {
        fputs(buf, out_1);
//        fputs(buf, out_2);
    }

    fflush(out_1);
//    fflush(out_2);
    fclose(out_1);
//    fclose(out_2);
    close(pipe_one[1]);
//    close(pipe_two[1]);

    wait(NULL);
    //wait(NULL);

    exit(EXIT_SUCCESS);
}

我已注释掉与第二个孩子有关的所有部分。如果我运行此程序,它将正常运行(它从stdin读取直到遇到EOF,然后将其打印到stdout中)。但是,如果我尝试用第二个分叉执行完全相同的操作(请参阅注释掉的部分),则它将执行完全相同的操作,除了在打印所有内容后程序不会终止。而且我还无法找到原因。

我的猜测是,我不会在两个孩子中重复两次stdinfileno。但是,我们的任务要求我们这样做。我有什么想念的吗?如果有人可以看看我,我将非常高兴!

c unix pipe fork
1个回答
0
投票

您没有在第一个孩子中关闭pipe_two[0]pipe_two[1]

您没有在第二个孩子中关闭pipe_one[0]pipe_one[1]


顺便说一句,

dup2(pipe_one[0], STDIN_FILENO);
close(pipe_one[0]);
while (fgets(buf, 100, stdin)) ...;

可以简化为

FILE *f = fdopen(pipe_one[0]);
while (fgets(buf, 100, f)) ...;
© www.soinside.com 2019 - 2024. All rights reserved.