简体   繁体   English

Unix C - 将stdout重定向到管道然后再返回到stdout

[英]Unix C - Redirecting stdout to pipe and then back to stdout

I'm not sure if the following can be done because I cannot find any questions/results via Google on it. 我不确定是否可以执行以下操作,因为我无法通过Google找到任何问题/结果。 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 你好,世界

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

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. 出于效率原因,FILE句柄在写入时并不总是立即产生输出。 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). 无缓冲的句柄总是立即写入(stderr是无缓冲的)。 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). 行缓冲句柄等到缓冲区已满或打印换行符( '\\n' )(如果stdout引用终端,则stdout为行缓冲)。 Block buffered handles wait until the buffer is full (stdout is block buffered if it doesn't refer to a terminal). 块缓冲句柄一直等到缓冲区已满(如果stdout没有引用终端,则stdout是块缓冲的)。

When your helloworld program starts up, stdout goes to a pipe, not a terminal, so it's set up as block buffered. 当你的helloworld程序启动时,stdout会进入管道,而不是终端,所以它被设置为块缓冲。 The printf calls therefore simply store the text in memory. 因此,printf调用只是将文本存储在内存中。 Since the buffer doesn't get full, it is only flushed when stdout is closed, which in this case happens when the program exits. 由于缓冲区未满,因此仅在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. 但是当程序退出时,文件描述符1(stdout)已经恢复,以引用父项的原始标准输出,而不是管道。 Thus the buffered output ends up being written to the original stdout. 因此,缓冲的输出最终被写入原始标准输出。

fflush forces the buffered text to be written immediately. fflush强制立即写入缓冲的文本。

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

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