重定向stdout,不明白行为

时间:2016-04-09 18:24:33

标签: c io dup2

我一直在尝试使用dup2进行简单的i / o重定向。我完全按照其他人所说的代码,但仍然没有成功。

int out = open("stdoutput", O_RDWR | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR);
printf("STANDARD OUT\n");
dup2(out, 1);
printf("SEND TO FILE\n");
dup2(1, out);
close(out);
printf("BACK TO STANDARD OUT\n");

将STANDARD OUT打印到终端和 发送到文件 回到标准输出 到文件。为什么不换回来?

我还希望将fork / exec输出标准输出到文件。

int out2 = open("execout", O_RDWR | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR);
printf("STANDARD OUT\n");
dup2(out2, 1);
if(fork() == 0)
{
    execvp("time", NULL);
    perror(NULL);
}

dup2(out2, 1);
close(out2);
printf("BACK TO STANDARD OUT\n");

打印到终端:

标准输出 TERM_PROGRAM = Apple_Terminal:没有这样的文件或目录         0.00 real 0.00 user 0.00 sys

和文件execout,它打印: 回到标准输出

exec调用时间似乎有一些额外的问题(没有找到它但是然后打印它?)但我的主要问题是I / O重定向无法正常工作。

提前感谢您的帮助。

更新:具体问题似乎是exec没有向文件发送输出。代码:

int output_file = open("gcc_output", O_RDWR | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR);

if(fork() == 0)
{
    dup2(output_file, 1);
    close(output_file);
    char *args[] = {"gcc", path, NULL};
    printf("THIS GOES TO FILE");
    execvp(args[0], args); // gcc output, errors etc. go to terminal
    perror("exec");
    exit(2);
}

exec会导致它丢失文件描述符吗?

1 个答案:

答案 0 :(得分:0)

dup2(from, to)将文件描述符from复制到文件描述符to;如果to已打开,则会在被覆盖之前以静默方式关闭。

在您的第一个示例中,您打开文件stdoutput进行写入;给出最低可能的描述符号(可能是3);然后你的dup2(out2, 1)将这个描述符复制到标准输出描述符1上;原始标准输出静默关闭。现在有4个开放描述符:

  • 0是原始标准输入
  • 打开
  • 1以写入文件stdoutput
  • 2是原始标准输出
  • 3打开以写入文件stdoutput

最后,您尝试通过在文件描述符3上复制文件描述符1来“恢复”原始标准输出。

相反,您应该通过dup原始标准输出存储到另一个文件描述符中:

int out = open("stdoutput", O_RDWR | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR);
printf("STANDARD OUT\n");
int saved_stdout = dup(1); // create a copy of the stdout file descriptor
dup2(out, 1);
close(out);                // close the extra descriptor
printf("SEND TO FILE\n");
dup2(saved_stdout, 1);     // copy the saved stdout file descriptor to 1
close(saved_stdout);       // close the copy of stdout
printf("BACK TO STANDARD OUT\n");

你的execvp电话也被打破了;应该有一个额外的参数,即命令名称;同时time不打印当前日期,但是是一个命令,它将另一个命令作为参数 - 也许你想要执行date命令?此外,您希望在fork之后在子进程中执行dup2 。请尝试以下方法:

int out2 = open("execout", O_RDWR | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR);
printf("STANDARD OUT\n");
if (fork() == 0) {
    dup2(out2, 1);
    close(out2);
    execvp("date", "date", (char *)NULL);
    perror("exec");
    exit(2);
}
close(out2);
printf("STILL POINTING TO STANDARD OUT\n");