简体   繁体   English

C:将标准输入,标准输出重定向到管道

[英]C: redirecting stdin, stdout to pipes

I'm in the process of properly understanding pipes and FDs and I'm trying to program the following thing: The program basically compresses stuff like gzip does with the options -cf. 我正在正确理解管道和FD的过程中,并且尝试对以下内容进行编程:该程序基本上像gzip那样使用-cf选项压缩内容。 The basic idea is: 基本思想是:

I create two pipes in the parent process, then I fork it twice so that I'll have two children. 我在父进程中创建了两个管道,然后将其分叉两次,以便有两个孩子。 In the first child, I redirect the first pipe's read end to stdin, and the second pipe's write end to stdout. 在第一个孩子中,我将第一个管道的读取端重定向到stdin,将第二个管道的写入端重定向到stdout。 Then I exec gzip with the -cf options so that it'll write to stdout (now the writing end of pipe2) 然后,我使用-cf选项执行gzip,以便将其写入stdout(现在是pipe2的写入端)

In the second child, I read from pipe2 and either output it directly or save it to a file. 在第二个孩子中,我从pipe2读取并直接输出它或将其保存到文件中。 The problem is, however, that no data arrives at the second child and I'm not really sure why. 但是问题是,没有数据到达第二个孩子,我不确定为什么。 Here's the code: 这是代码:

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;
}

Please excuse the missing error handling as I wanted to create a quick-and-dirty version. 请原谅缺少的错误处理,因为我想创建一个快捷的版本。

Any help is appreciated. 任何帮助表示赞赏。

In the parent process, you are closing both ends of c2pipe before you have forked the second child. 在父进程中,在分叉第二个孩子之前,您将关闭c2pipe的两端。

You'd probably have figured this out already if you had put any error handling in on any of the read/write calls. 如果您在任何读/写调用中都进行了错误处理,那么您可能已经想通了。 In fact, if you checked for an error on the dup2 calls and then looked at errno, you probably would have found that it was EBADF (bad file descriptor). 实际上,如果在dup2调用中检查错误,然后查看errno,则可能会发现它是EBADF (错误的文件描述符)。

Another issue is that your parent process exits before it knows that both child processes have finished. 另一个问题是您的父进程在知道两个子进程都已完成之前退出。 This means that the child processes will receive a signal and will themselves be terminated. 这意味着子进程将接收信号,并且自身将终止。 The parent needs to call one of the variants of wait() to make sure both children have gone. 父母需要调用wait()的变体之一,以确保两个孩子都离开了。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM