ホームページ >バックエンド開発 >C++ >Linux で標準入出力を子プロセスに適切にパイプするにはどうすればよいですか?

Linux で標準入出力を子プロセスに適切にパイプするにはどうすればよいですか?

Linda Hamilton
Linda Hamiltonオリジナル
2024-11-08 19:39:02282ブラウズ

How can I properly pipe standard input and output to a child process in Linux?

Linux でパイプされた標準入出力を使用して子プロセスを実行する

次の関数を考えてみましょう:

string f(string s) {
    string r = system("foo < s");
    return r;
}

This関数は、文字列 s を標準入力として使用して「foo」プログラムを実行しようとし、プログラムの標準出力をキャプチャします。文字列 r。ただし、このアプローチは実行できません。

この機能を正しく実装するには、Linux システム コールまたは POSIX 関数の組み合わせが必要です。

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>

int createChild(const char *szCommand, char *const aArguments[], char *const aEnvironment[],
               const char *szMessage) {
  int aStdinPipe[2];
  int aStdoutPipe[2];
  int nChild;
  char nChar;

  if (pipe(aStdinPipe) < 0) {
    perror("allocating pipe for child input redirect");
    return -1;
  }
  if (pipe(aStdoutPipe) < 0) {
    close(aStdinPipe[PIPE_READ]);
    close(aStdinPipe[PIPE_WRITE]);
    perror("allocating pipe for child output redirect");
    return -1;
  }

  nChild = fork();
  if (0 == nChild) {
    // child continues here

    // redirect stdin
    if (dup2(aStdinPipe[PIPE_READ], STDIN_FILENO) == -1) {
      exit(errno);
    }

    // redirect stdout
    if (dup2(aStdoutPipe[PIPE_WRITE], STDOUT_FILENO) == -1) {
      exit(errno);
    }

    // redirect stderr
    if (dup2(aStdoutPipe[PIPE_WRITE], STDERR_FILENO) == -1) {
      exit(errno);
    }

    // run child process image
    // (replace this with any `exec*` function you find easier to use)
    execve(szCommand, aArguments, aEnvironment);

    // if we get here at all, an error occurred, but we are in the child
    // process, so just exit
    exit(errno);
  } else if (nChild > 0) {
    // parent continues here

    // close unused file descriptors
    close(aStdinPipe[PIPE_READ]);
    close(aStdoutPipe[PIPE_WRITE]);

    // send message to child (if provided)
    if (NULL != szMessage) {
      write(aStdinPipe[PIPE_WRITE], szMessage, strlen(szMessage));
    }

    // read child's output
    while (read(aStdoutPipe[PIPE_READ], &nChar, 1) == 1) {
      write(STDOUT_FILENO, &nChar, 1);
    }

    // close pipes
    close(aStdinPipe[PIPE_WRITE]);
    close(aStdoutPipe[PIPE_READ]);
  } else {
    // failed to create child
    close(aStdinPipe[PIPE_READ]);
    close(aStdinPipe[PIPE_WRITE]);
    close(aStdoutPipe[PIPE_READ]);
    close(aStdoutPipe[PIPE_WRITE]);
  }
  return nChild;
}

この関数 createChild は、親プロセスと子プロセスが、子の標準入出力をパイプとの間でリダイレクトします。親プロセスは、パイプ経由で子に入力を送信し、同じパイプから子の出力を読み取ることができます。

以上がLinux で標準入出力を子プロセスに適切にパイプするにはどうすればよいですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。