C言語入門講座。関数、サンプル集を参考にして、 C言語をマスターしよう。初心者から上級者まで。

パイプを生成する

2012.08.10

pipe関数は、パイプを生成します。パイプとは、通常のファイルの入出力と同じような操作で、プロセス間でのデータのやりとりを行う仕組みです。

この関数は、C言語のライブラリ関数(標準関数)ではありませんので、コンパイラにより、使えない場合があります。

#include <unistd.h>
int pipe(int pipefd[2]);

pipefd[2]はパイプの両端を参照するファイル・ディスクリプタを格納する配列を指定します。

戻り値として、処理が成功した場合は0が、エラーの場合は-1を返します。

引数のpipefd[2]のpipefd[0]がパイプの読み出し側で、pipefd[1]がパイプの書き込み側です。例えば、親プロセスから子プロセスにデータを送る場合は、親プロセスはpipefd[1]を使ってデータを出力して、子プロセスはpipefd[0]を使ってデータを入力します。

プログラム 例

#include <stdio.h>
#include <unistd.h>
#include <sys/wait.h>
#include <stdlib.h>
#include <string.h>
#define BUFF_SIZE 1024

int main(int argc, char **argv)
{
  int         pipefd[2];
  int         p_id;
  int         status;
  FILE        *fp;
  char        buff[BUFF_SIZE];

  if (argc != 2) {
    fprintf(stderr, 'main : 実行時引数の数が不当です\n');
    exit(EXIT_FAILURE);
  }

  if (pipe(pipefd) == -1) {
    perror('main ');
    exit(EXIT_FAILURE);
  }

  if ((p_id = fork()) == -1) {
    perror('main ');
    exit(EXIT_FAILURE);
  }

  if (p_id == 0) {
    /* 子プロセス */
    /* 使用しないwrite側はクローズ */
    close(pipefd[1]);
    /* パイプから読み込む */
    while (read(pipefd[0], &buff, BUFF_SIZE) > 0) {
      fputs(buff, stdout);
    }
    close(pipefd[0]);
  }
  else {
    /* 親プロセス */
    /* 使用しないread側はクローズ */
    close(pipefd[0]);

    if ((fp = fopen(*(argv + 1), 'r')) != NULL) {
      while(fgets(buff, BUFF_SIZE, fp) != NULL) {
        /* パイプに書き込む */
        write(pipefd[1], buff, strlen(buff) + 1);
      }

      fclose(fp);
    }
    else {
      perror('親プロセス ');
    }

    close(pipefd[1]);
    wait(&status);
  }

  return EXIT_SUCCESS;
}

例の実行結果

$ cat temp_1.txt
Hello World!!.
Bye.
$
$ ./pipe.exe temp_1.txt
Hello World!!.
Bye.
$

関連記事