Share via


_pipe

更新 : 2007 年 11 月

読み取りおよび書き込み用のパイプを作成します。

int _pipe(
   int *pfds,
   unsigned int psize,
   int textmode 
);

パラメータ

  • pfds[2]
    読み取りファイル記述子と書き込みファイル記述子を保持する配列。

  • psize
    予約するメモリの容量。

  • textmode
    ファイル モード。

戻り値

処理が正常に終了した場合は 0 を返します。エラーを示す場合は –1 を返します。この場合、errno が次の 3 つの値のいずれかに設定されます。EMFILE は、それ以上使用できるファイル記述子がないことを示します。ENFILE は、システム ファイル テーブルのオーバーフローを示します。EINVAL は、配列 pfds が null ポインタであったか、または textmode に無効な値が渡されたことを示します。

リターン コードの詳細については、「_doserrno、errno、_sys_errlist、および _sys_nerr」を参照してください。

解説

_pipe 関数はパイプを作成します。パイプは、プログラム間で情報を受け渡すために使用する架空の入出力チャネルです。ファイルと同様、パイプもファイル ポインタやファイル記述子 (またはその両方) を持っているため、標準ライブラリの入出力関数を使用した読み取りや書き込みが可能です。ただし、パイプが表しているのは特定のファイルやデバイスではなく、メモリ内の一時的な記憶領域に過ぎません。この記憶領域は、プログラムに割り当てられているメモリとは別に確保され、オペレーティング システムによって全面的に制御されます。

_pipe 関数は _open 関数に似ていますが、読み取り用と書き込み用にパイプを開くため、1 つではなく 2 つのファイル記述子を返します。プログラムでは、ファイル ハンドルを両方とも使用できますが、不要な場合は片方を閉じることもできます。たとえば、Windows NT のコマンド プロセッサは、次のようなコマンドを実行するとパイプを作成します。

PROGRAM1 | PROGRAM2

PROGRAM1 の標準出力記述子はパイプの書き込み記述子に結合され、PROGRAM2 の標準入力記述子はパイプの読み取り記述子に結合されます。これにより、情報をほかのプログラムに渡すために一時ファイルを作成する必要がなくなります。

_pipe 関数は、引数 pfds で指定されている、パイプへの 2 つのファイル記述子を返します。要素 pfds[0] には読み取り記述子、要素 pfds[1] には書き込み記述子が格納されます。パイプのファイル記述子の使い方は、他のファイル記述子の場合と同様です。たとえば、下位の入出力関数である _read および _write で、パイプに対する読み書きが可能です。パイプの終端を検出するには、_read 要求が返す値 (読み取られたバイト数を示す値) が 0 かどうかを調べます。

引数 psize には、パイプ用に予約するメモリの容量をバイト単位で指定します。引数 textmode には、パイプで使用する変換モードを指定します。記号定数 _O_TEXT はテキスト変換モード、定数 _O_BINARY はバイナリ変換モードを指定します。テキスト変換モードとバイナリ変換モードの詳細については、fopen の説明を参照してください。引数 textmode に 0 を指定すると、_pipe 関数は変数 _fmode で指定されている既定の変換モードを使用します。

マルチスレッド プログラムの場合、ロックは実行されません。返されたファイル記述子は新しく開かれるため、_pipe 関数の呼び出しが完了するまでは、他のスレッドから参照しないでください。

_pipe 関数を使用して親プロセスと子プロセス間で通信するには、各プロセスがパイプの記述子を 1 つだけ開き、それぞれが開いている記述子が対応している必要があります。つまり、親プロセスが読み取り記述子を開いている場合、子プロセスでは書き込み記述子を開いておく必要があります。この対応関係を簡単に実現するには、textmode_O_NOINHERIT フラグの OR (|) を受け取り、その後、_dup 関数または _dup2 関数を使用して子プロセスに渡すパイプ記述子の継承できるコピーを作成します。元の記述子を閉じてから、子プロセスを呼び出します。呼び出した子プロセスから戻ったときに、複製された記述子を親プロセスで閉じます。詳細については、後の「例 2」を参照してください。

Windows オペレーティング システムでは、すべての記述子を閉じたとき、パイプが破棄されます。パイプの読み取り記述子をすべて閉じた場合、パイプに書き込みを行うとエラーが発生します。パイプに対するすべての読み書き操作は、入出力要求を完了するために必要なデータまたはバッファが確保されるまで待機します。

必要条件

ルーチン

必須ヘッダー

オプション ヘッダー

_pipe

<io.h>

<fcntl.h>,1 <errno.h>2

1 _O_BINARY 定義および _O_TEXT 定義について

2 errno 定義

互換性の詳細については、「C ランタイム ライブラリ」の「互換性」を参照してください。

ライブラリ

C ランタイム ライブラリのすべてのバージョン。

例 1

// crt_pipe.c
/* This program uses the _pipe function to pass streams of
 * text to spawned processes.
 */

#include <stdlib.h>
#include <stdio.h>
#include <io.h>
#include <fcntl.h>
#include <process.h>
#include <math.h>

enum PIPES { READ, WRITE }; /* Constants 0 and 1 for READ and WRITE */
#define NUMPROBLEM 8

int main( int argc, char *argv[] )
{

   int fdpipe[2];
   char hstr[20];
   int pid, problem, c;
   int termstat;

   /* If no arguments, this is the spawning process */
   if( argc == 1 )
   {

      setvbuf( stdout, NULL, _IONBF, 0 );

      /* Open a set of pipes */
      if( _pipe( fdpipe, 256, O_BINARY ) == -1 )
          exit( 1 );


      /* Convert pipe read descriptor to string and pass as argument 
       * to spawned program. Program spawns itself (argv[0]).
       */
      _itoa_s( fdpipe[READ], hstr, sizeof(hstr), 10 );
      if( ( pid = _spawnl( P_NOWAIT, argv[0], argv[0], 
            hstr, NULL ) ) == -1 )
          printf( "Spawn failed" );

      /* Put problem in write pipe. Since spawned program is 
       * running simultaneously, first solutions may be done 
       * before last problem is given.
       */
      for( problem = 1000; problem <= NUMPROBLEM * 1000; problem += 1000)
      {

         printf( "Son, what is the square root of %d?\n", problem );
         _write( fdpipe[WRITE], (char *)&problem, sizeof( int ) );

      }

      /* Wait until spawned program is done processing. */
      _cwait( &termstat, pid, WAIT_CHILD );
      if( termstat & 0x0 )
         printf( "Child failed\n" );


      _close( fdpipe[READ] );
      _close( fdpipe[WRITE] );

   }

   /* If there is an argument, this must be the spawned process. */
   else
   {

      /* Convert passed string descriptor to integer descriptor. */
      fdpipe[READ] = atoi( argv[1] );

      /* Read problem from pipe and calculate solution. */
      for( c = 0; c < NUMPROBLEM; c++ )
      {

        _read( fdpipe[READ], (char *)&problem, sizeof( int ) );
        printf( "Dad, the square root of %d is %3.2f.\n",
                 problem, sqrt( ( double )problem ) );

      }
   }
}

出力例

Son, what is the square root of 1000?
Son, what is the square root of 2000?
Son, what iDad, the square root of 1000 is 31.62.
Dad, the square root of 2000 is 44.72.
s the square root of 3000?
Dad, the square root of 3000 is 54.77.
Son, what is the square root of 4000?
Dad, the square root of 4000 is 63.25.
Son, what is the square root of 5000?
Dad, the square root of 5000 is 70.71.
Son, what is the square root of 6000?
SonDad, the square root of 6000 is 77.46.
, what is the square root of 7000?
Dad, the square root of 7000 is 83.67.
Son, what is the square root of 8000?
Dad, the square root of 8000 is 89.44.

例 2

次に示すのは、簡単なフィルタ アプリケーションの例です。crt_pipe_beeper アプリケーションを生成する前に、アプリケーションの標準出力 (stdout) をフィルタに渡すパイプを作成します。フィルタは、ASCII 7 (ビープ音) 文字を削除します。

// crt_pipe_beeper.c

#include <stdio.h>
#include <string.h>

int main()
{
   int   i;
   for(i=0;i<10;++i)
      {
         printf("This is speaker beep number %d...\n\7", i+1);
      }
   return 0;
}

実際のフィルタ アプリケーションは、次のとおりです。

// crt_pipe_BeepFilter.C
// arguments: crt_pipe_beeper.exe

#include <windows.h>
#include <process.h>
#include <memory.h>
#include <string.h>
#include <stdio.h>
#include <fcntl.h>
#include <io.h>

#define   OUT_BUFF_SIZE 512
#define   READ_FD 0
#define   WRITE_FD 1
#define   BEEP_CHAR 7

char szBuffer[OUT_BUFF_SIZE];

int Filter(char* szBuff, ULONG nSize, int nChar)
{
   char* szPos = szBuff + nSize -1;
   char* szEnd = szPos;
   int nRet = nSize;

   while (szPos > szBuff)
   {
      if (*szPos == nChar)
         {
            memmove(szPos, szPos+1, szEnd - szPos);
            --nRet;
         }
      --szPos;
   }
   return nRet;
}

int main(int argc, char** argv)
{
   int nExitCode = STILL_ACTIVE;
   if (argc >= 2)
   {
      HANDLE hProcess;
      int fdStdOut;
      int fdStdOutPipe[2];

      // Create the pipe
      if(_pipe(fdStdOutPipe, 512, O_NOINHERIT) == -1)
         return   1;

      // Duplicate stdout file descriptor (next line will close original)
      fdStdOut = _dup(_fileno(stdout));

      // Duplicate write end of pipe to stdout file descriptor
      if(_dup2(fdStdOutPipe[WRITE_FD], _fileno(stdout)) != 0)
         return   2;

      // Close original write end of pipe
      _close(fdStdOutPipe[WRITE_FD]);

      // Spawn process
      hProcess = (HANDLE)_spawnvp(P_NOWAIT, argv[1], 
       (const char* const*)&argv[1]);

      // Duplicate copy of original stdout back into stdout
      if(_dup2(fdStdOut, _fileno(stdout)) != 0)
         return   3;

      // Close duplicate copy of original stdout
      _close(fdStdOut);

      if(hProcess)
      {
         int nOutRead;
         while   (nExitCode == STILL_ACTIVE)
         {
            nOutRead = _read(fdStdOutPipe[READ_FD], 
             szBuffer, OUT_BUFF_SIZE);
            if(nOutRead)
            {
               nOutRead = Filter(szBuffer, nOutRead, BEEP_CHAR);
               fwrite(szBuffer, 1, nOutRead, stdout);
            }

            if(!GetExitCodeProcess(hProcess,(unsigned long*)&nExitCode))
               return 4;
         }
      }
   }
   return nExitCode;
}

出力

This is speaker beep number 1...
This is speaker beep number 2...
This is speaker beep number 3...
This is speaker beep number 4...
This is speaker beep number 5...
This is speaker beep number 6...
This is speaker beep number 7...
This is speaker beep number 8...
This is speaker beep number 9...
This is speaker beep number 10...

.NET Framework の相当するアイテム

適用できません。標準 C 関数を呼び出すには、PInvoke を使用します。詳細については、「プラットフォーム呼び出しの例」を参照してください。

参照

参照

プロセス制御と環境制御

_open、_wopen