试图实现重定向。无法理解文件描述符和dup2

时间:2013-05-29 06:48:43

标签: c

我应该实现一个具有重定向功能的shell,但我在如何处理文件描述符方面遇到了麻烦。 在我的test.c文件中,我正在尝试,尝试将测试从'python --version'管道传输到名为'out'的文件中。

int main(int argc, char *argv[], char *const envp[])
{
/***/TOKENIZER *tester;
    int pid = 0;
    int pipefd[2];
    char buffer = 0;

    pipe(pipefd); 
    pid = fork();
    pipefd[1] = open("out", O_WRONLY | O_TRUNC | O_CREAT, S_IRUSR | S_IRGRP | S_IWGRP | S_IWUSR);

    if(pid == 0){
        close(pipefd[1]);
        dup2(pipefd[0], STDIN_FILENO); 
        close(pipefd[0]);
        while(read(STDIN_FILENO, &buffer, 1) > 0){
            write(STDOUT_FILENO, &buffer, 1);
        }

        close(pipefd[0]);
        _exit(EXIT_SUCCESS);
    }else{
        close(pipefd[0]);
        dup2(pipefd[1], STDOUT_FILENO); 
        close(pipefd[1]);

        write(STDOUT_FILENO, "asdsd\n", 6);

        char* ver[2];
        ver[1] = "--version";
        execvp("python", ver);
        exit(EXIT_SUCCESS);
    }
    free(tester);


    return 0;
编辑:已实现我正在混合部分重定向和管道。这是我试图运行的一些重定向代码。

int out = open("output.txt", O_WRONLY | O_TRUNC | O_CREAT, S_IRUSR | S_IRGRP | S_IWGRP | S_IWUSR);

dup2(out, 1);
close(out);

char* ver[2];
ver[1] = "--version";
execvp("python", ver);
exit(EXIT_SUCCESS);

return 0;

我正在尝试将Python版本化到output.txt中,但我似乎错过了一些东西,因为它不起作用。

编辑2:看起来它正在执行,但它输出到标准输出而不是output.txt。

int out = open("output.txt", O_WRONLY | O_TRUNC | O_CREAT, S_IRUSR | S_IRGRP | S_IWGRP | S_IWUSR);
dup2(out, STDOUT_FILENO);

char* ver[3];
ver[0] = "python";
ver[1] = "--version";
ver[2] = NULL;
execvp("python", ver);
perror("exec");

return 0;

1 个答案:

答案 0 :(得分:1)

    int pid = 0;
    int pipefd[2];
    char buffer = 0;

    pipe(pipefd); 
    pid = fork();

到目前为止,这么好。您已创建了一个管道,其两个文件描述符存储在pipefd[0]pipefd[1]中,并创建了一个子进程。

    pipefd[1] = open("out", O_WRONLY | O_TRUNC | O_CREAT, S_IRUSR | S_IRGRP | S_IWGRP | S_IWUSR);

哦不!你只是用一个不同的文件描述符覆盖了一个非常好的文件描述符(管道的写入端),指向名为“out”的常规文件。

您是否尝试进行常规文件重定向或管道?在尝试实现shell之前,您应该至少知道这些是两个不同的东西。如果您正在尝试模仿python --version > out,那么您应该注意到该命令行中没有管道符,那么为什么您会想到实现中涉及管道?

此外,由于您在fork之后执行了此操作,因此两个进程现在都在运行,并且它们都将打开,包括创建和截断副作用。那可能不是你想要的。

我会停在那里,因为在你修复这个部分之前,程序的其余部分是没有意义的。

但随便注意几句:

  • 3-arg main已经淘汰了很长一段时间。使用getenv()environ查找环境变量。
  • 单字节缓冲区效率不高,使用较大的缓冲区并不困难。
  • 这很奇怪 - 不一定是致命的问题,但绝对不寻常 - 在父母而不是在孩子身上做执行。