【问题标题】:C: redirecting stdin, stdout to pipesC:将标准输入、标准输出重定向到管道
【发布时间】:2016-04-26 23:54:03
【问题描述】:

我正在正确理解管道和 FD,我正在尝试编写以下内容: 该程序基本上使用选项 -cf 压缩 gzip 之类的东西。 基本思路是:

我在父进程中创建了两个管道,然后我分叉了两次,这样我就有了两个孩子。在第一个孩子中,我将第一个管道的读取端重定向到标准输入,将第二个管道的写入端重定向到标准输出。然后我使用 -cf 选项执行 gzip,以便它写入标准输出(现在是 pipe2 的写入端)

在第二个孩子中,我从 pipe2 读取并直接输出或将其保存到文件中。 然而,问题是没有数据到达第二个孩子,我不确定为什么。代码如下:

int main(int argc, char **argv) {
    char *file;
    int out = 0;
    if(argc == 2) {
        file = argv[1];
        out = 1;
    } else if (argc > 2) {
        exit(EXIT_FAILURE);         
    }

    int c1pipe[2];
    int c2pipe[2];
    pipe(c1pipe);
    pipe(c2pipe);

    int f;    
    for(int i = 0; i < 2; i++) {
        switch(f = fork()) {
            case 0: //child
                if(i == 0) { //first loop iteration, child 1
                    close(c1pipe[1]); 
                    dup2(c1pipe[0], fileno(stdin));
                    close(c1pipe[0]); 
                    close(c2pipe[0]); 
                    dup2(c2pipe[1], fileno(stdout));
                    close(c2pipe[1]); 
                    execlp("gzip", "gzip", "-cf", (char *) NULL);
                } else if (i == 1) { //second loop iteration, child2
                    close(c1pipe[0]);
                    close(c1pipe[1]);
                    close(c2pipe[1]);
                    FILE *read = fdopen(c2pipe[0], "r");    
                    char buffer[1024];

                    if(out == 0) { //output to stdout
                        while(fgets(buffer, 1024, read) != NULL) {
                            fprintf(stdout, "%s", buffer);
                            fflush(stdout);
                        }
                    } else { //write to specified file
                        FILE *writeto = fopen(file, "w");
                        while(fread(buffer, sizeof(char), strlen(buffer)+1, read) > 0) {
                            fwrite(buffer, sizeof(char), strlen(buffer)+1, writeto);
                            fflush(writeto);
                        }
                        fclose(writeto);
                    }

                    close(c2pipe[0]);
                    fclose(read);
                }           
            break;
            case -1: //err
                //not implemented
            break;
            default: //parent
                if(i == 0) {
                    close(c2pipe[0]);
                    close(c2pipe[1]);
                    close(c1pipe[0]);
                    FILE *writer;
                    writer = fdopen(c1pipe[1], "w");
                    char buffer[1024];
                    while(fgets(buffer, sizeof buffer, stdin) != NULL) {
                        fwrite(buffer, sizeof (char), strlen(buffer)+1, writer);
                    }
                    close(c1pipe[1]);
                    fclose(writer);
                }
            break;
        }
    }

    return 0;
}

请原谅缺少的错误处理,因为我想创建一个快速而肮脏的版本。

感谢任何帮助。

【问题讨论】:

    标签: c pipe fork io-redirection


    【解决方案1】:

    在父进程中,您在分叉第二个孩子之前关闭了 c2pipe 的两端。

    如果您对任何读/写调用进行了任何错误处理,您可能已经知道这一点。事实上,如果您检查 dup2 调用的错误,然后查看 errno,您可能会发现它是 EBADF(错误的文件描述符)。

    另一个问题是您的父进程在知道两个子进程都已完成之前就退出了。这意味着子进程将收到一个信号并自行终止。父母需要调用wait() 的变体之一以确保两个孩子都已离开。

    【讨论】:

    • 谢谢,有道理。我确实尝试将关闭 c2pipe 移动到父级循环的第二次迭代,但这没有帮助。事实上,似乎第一个孩子根本没有收到任何数据,我真的不知道为什么。我想我会尝试为此添加一些错误处理,也许它会解决问题。
    • @skulpt 我发现了另一个问题。我已经更新了答案。
    • 谢谢,好像是这样。现在我实际上得到了输出。我不知道父母会向孩子发送终止信号——我知道孤儿进程存在,我只是假设在这种情况下它们会成为孤儿,而不会终止。非常感谢您解决这个问题。
    猜你喜欢
    • 1970-01-01
    • 2013-02-10
    • 1970-01-01
    • 1970-01-01
    • 2013-07-16
    • 2012-05-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多