Unix C - 将标准输出重定向到管道,然后再重定向回标准输出

4

我不确定以下操作是否可行,因为我在Google上找不到任何相关问题或结果。我想要将fork()的stdout更改为管道(pipe),然后再将其改回普通的stdout。

这是我的代码:

FirstExecutable:

int main()
{
      int fd[2]; //Used for pipe
      int processID;

      if(pipe(fd) == -1)
      {
            printf("Error - Pipe error.\n");
            exit(EXIT_FAILURE);
      }

      if((processID = fork()) == -1)
      {
            fprintf(stderr, "fork failure");
            exit(EXIT_FAILURE);
      }

      if(processID == 0)
      {
           int newFD = dup(STDOUT_FILENO);

          char newFileDescriptor[2];

          sprintf(newFileDescriptor, "%d", newFD);

          dup2 (fd[1], STDOUT_FILENO);

          close(fd[0]);

          execl("./helloworld", "helloworld", newFileDescriptor, NULL);
      }
      else
      { 
          close(fd[1]);

          char c[10];

          int r = read(fd[0],c, sizeof(char) * 10);

          if(r > 0)
               printf("PIPE INPUT = %s", c);
      }
}

你好世界

int main(int argc, char **argv)
{
      int oldFD = atoi(argv[1]);

      printf("hello\n"); //This should go to pipe

      dup2(oldFD, STDOUT_FILENO);

      printf("world\n"); //This should go to stdout
}

期望的输出结果:

world
PIPE OUTPUT = hello

实际输出:

hello
world

1
man perror 不要使用 fprintf 来打印没有 strerror 的错误消息。 - William Pursell
1个回答

3
尝试更改。
  printf("hello\n");

to

  printf("hello\n");
  fflush(stdout);

这里的问题是缓冲。为了提高效率,当数据被写入时,文件句柄并不总是立即产生输出,而是将文本累积在内部缓冲区中。
有三种缓冲模式:无缓冲、行缓冲和块缓冲。无缓冲句柄总是立即写入(stderr 是无缓冲的)。行缓冲句柄会等到缓冲区满或者打印换行符('\n')时再输出(如果 stdout 指向终端,则是行缓冲的)。块缓冲句柄会等到缓冲区满时才输出(如果 stdout 不指向终端,则是块缓冲的)。
当你的 helloworld 程序启动时,stdout 指向一个管道而不是终端,所以它被设置为块缓冲。因此,printf 调用只是将文本存储在内存中。由于缓冲区没有被填满,所以只有当 stdout 被关闭时(在这种情况下,程序退出时),缓冲区才被刷新。
但是,当程序退出时,文件描述符 1 (stdout) 已经被恢复为指向父进程的原始 stdout,而不是管道。因此,缓冲输出最终被写入到原始的 stdout 上。 fflush 可以强制将缓冲文本立即写入。

运行得非常好!fflush()函数到底是做什么的,为什么它可以解决我的问题?如果您不介意我问的话!另外,再过6分钟后我会接受这个答案。 - MrHappyAsthma

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接