4

Google経由で質問/結果が見つからないため、次のことができるかどうかわかりません。fork() の stdout をパイプに変更してから、通常の stdout に戻したいと考えています。

これは私が持っているものです:

最初の実行可能ファイル:

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
4

1 に答える 1

3

変更してみる

  printf("hello\n");

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

ここでの問題はバッファリングです。効率上の理由から、FILE ハンドルは、書き込まれたときに常にすぐに出力を生成するとは限りません。代わりに、テキストを内部バッファーに蓄積します。

バッファリング モードには、アンバッファ、ライン バッファ、ブロック バッファの 3 つがあります。バッファリングされていないハンドルは常にすぐに書き込みます (stderr はバッファリングされません)。行バッファー処理されたハンドルは、バッファーがいっぱいになるか、改行 ( '\n') が出力されるまで待機します (端末を参照する場合、stdout は行バッファー処理されます)。ブロック バッファリングされたハンドルは、バッファがいっぱいになるまで待機します (端末を参照しない場合、stdout はブロック バッファリングされます)。

helloworld プログラムが起動すると、stdout は端末ではなくパイプに送られるため、ブロック バッファーとして設定されます。したがって、printf 呼び出しは単にテキストをメモリに保存します。バッファーはいっぱいにならないため、stdout が閉じられたときにのみフラッシュされます。この場合、プログラムの終了時に発生します。

しかし、プログラムが終了するまでに、ファイル記述子 1 (stdout) は、パイプではなく、親の元の stdout を参照するように復元されています。したがって、バッファリングされた出力は元の stdout に書き込まれます。

fflushバッファリングされたテキストがすぐに書き込まれるように強制します。

于 2013-02-25T03:48:32.707 に答える