将stdout重定向到管道,然后返回到stdout

时间:2021-10-14 20:57:02

I'm not sure if the following can be done because I cannot find any questions/results via Google on it. I want to change stdout of a fork() to a pipe, and then change it back to the normal stdout.

我不确定是否可以执行以下操作,因为我无法通过谷歌找到任何问题/结果。我想将fork()的stdout更改为管道,然后将其更改为普通的stdout。

This is what I have:

这就是我所拥有的:

FirstExecutable:

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

helloworld

helloworld

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
}

Desired Output:

期望的输出:

world
PIPE OUTPUT = hello

Actual Output:

实际输出:

hello
world

1 个解决方案

#1


3  

Try changing

试着改变

  printf("hello\n");

to

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

The issue here is buffering. For efficiency reasons FILE handles don't always produce output immediately when written to. Instead they accumulate text in an internal buffer.

这里的问题是缓冲。出于效率原因,文件句柄在写入时并不总是立即产生输出。相反,它们在内部缓冲区中积累文本。

There are three buffering modes, unbuffered, line buffered, and block buffered. Unbuffered handles always write immediately (stderr is unbuffered). Line buffered handles wait until the buffer is full or a newline ('\n') is printed (stdout is line buffered if it refers to a terminal). Block buffered handles wait until the buffer is full (stdout is block buffered if it doesn't refer to a terminal).

有三种缓冲模式:无缓冲、行缓冲和块缓冲。未缓冲句柄总是立即写入(stderr是未缓冲的)。行缓冲句柄要等到缓冲区满了或者打印了换行符(如果是终端,则为行缓冲)。块缓冲句柄要等到缓冲区满了(如果不引用终端,则stdout是块缓冲)。

When your helloworld program starts up, stdout goes to a pipe, not a terminal, so it's set up as block buffered. The printf calls therefore simply store the text in memory. Since the buffer doesn't get full, it is only flushed when stdout is closed, which in this case happens when the program exits.

当helloworld程序启动时,stdout会进入一个管道,而不是一个终端,因此它被设置为块缓冲。因此,printf调用只需将文本存储在内存中。由于缓冲区没有满,所以只有在关闭stdout时才刷新缓冲区,在这种情况下,当程序退出时才会刷新缓冲区。

But by the time the program exits, file descriptor 1 (stdout) has been restored to refer to the parent's original stdout, not the pipe. Thus the buffered output ends up being written to the original stdout.

但是当程序退出时,文件描述符1 (stdout)已经被还原为引用父类的原始stdout,而不是管道。因此,缓冲输出最终被写入到原始stdout。

fflush forces the buffered text to be written immediately.

fflush迫使缓冲文本立即被写入。

#1


3  

Try changing

试着改变

  printf("hello\n");

to

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

The issue here is buffering. For efficiency reasons FILE handles don't always produce output immediately when written to. Instead they accumulate text in an internal buffer.

这里的问题是缓冲。出于效率原因,文件句柄在写入时并不总是立即产生输出。相反,它们在内部缓冲区中积累文本。

There are three buffering modes, unbuffered, line buffered, and block buffered. Unbuffered handles always write immediately (stderr is unbuffered). Line buffered handles wait until the buffer is full or a newline ('\n') is printed (stdout is line buffered if it refers to a terminal). Block buffered handles wait until the buffer is full (stdout is block buffered if it doesn't refer to a terminal).

有三种缓冲模式:无缓冲、行缓冲和块缓冲。未缓冲句柄总是立即写入(stderr是未缓冲的)。行缓冲句柄要等到缓冲区满了或者打印了换行符(如果是终端,则为行缓冲)。块缓冲句柄要等到缓冲区满了(如果不引用终端,则stdout是块缓冲)。

When your helloworld program starts up, stdout goes to a pipe, not a terminal, so it's set up as block buffered. The printf calls therefore simply store the text in memory. Since the buffer doesn't get full, it is only flushed when stdout is closed, which in this case happens when the program exits.

当helloworld程序启动时,stdout会进入一个管道,而不是一个终端,因此它被设置为块缓冲。因此,printf调用只需将文本存储在内存中。由于缓冲区没有满,所以只有在关闭stdout时才刷新缓冲区,在这种情况下,当程序退出时才会刷新缓冲区。

But by the time the program exits, file descriptor 1 (stdout) has been restored to refer to the parent's original stdout, not the pipe. Thus the buffered output ends up being written to the original stdout.

但是当程序退出时,文件描述符1 (stdout)已经被还原为引用父类的原始stdout,而不是管道。因此,缓冲输出最终被写入到原始stdout。

fflush forces the buffered text to be written immediately.

fflush迫使缓冲文本立即被写入。