pipe の機能の発揮を見てもらう前に簡単な pipe による標準入出力の結合を紹介しよう。
次の例は同一プロセス内での標準出力( STDOUT ) を標準入力( STDIN ) にリダイレクトさせる例である。
------------------------------------------------------------------------------- 0001.00 #include <stdio.h> 0002.00 #include <stdlib.h> 0003.00 #include <string.h> 0004.00 #include <unistd.h> 0005.00 0006.00 #define TRUE 0 0007.00 #define FALSE -1 0008.00 0009.00 void main(void){ 0010.00 int fildes[2]; 0011.00 int rc, bytesWritten, bytesRead; 0012.00 char writeData[10], readData[11]; 0013.00 0014.00 printf("** TESTPIPE: PIPE のテスト ***\n"); 0015.00 getchar(); 0016.00 0017.00 memset(writeData, 'A', 10); 0018.00 0019.00 /*(1) fildes[0] と fildes[1] を pipe で結ぶ */ 0020.00 pipe(fildes); 0021.00 0022.00 /*(2) fildes[1] に文字列 writeData を出力する */ 0023.00 if((bytesWritten = write(fildes[1], writeData, 10)) == FALSE){ 0024.00 perror("write error"); 0025.00 } 0026.00 else{/* 成功 */ 0027.00 printf("wrote %d bytes\n", bytesWritten); 0028.00 /*(3) fildes[0] から文字列 readData を読み取る */ 0029.00 if((bytesRead = read(fildes[0], readData, 10)) == FALSE){ 0030.00 perror("read error"); 0031.00 } 0032.00 else{/* 読取り成功 */ 0033.00 /*(4) fildes[0] からの読み取り結果を表示する */ 0034.00 printf("read %d bytes\n", bytesRead); 0035.00 readData[10] = 0x00; 0036.00 printf("readData is [%s]\n", readData); 0037.00 }/* 読取り成功 */ 0038.00 }/* 成功 */ 0039.00 close(fildes[0]); 0040.00 close(fildes[1]); 0041.00 0042.00 getchar(); 0043.00 } -------------------------------------------------------------------------------
実行すると次のような結果が表示される。
【解説】
最初に 0010.00 int fildes[2]; によって 2項目のファイル識別子のセットを用意しておく。
次に、
0019.00 /*(1) fildes[0] と fildes[1] を pipe で結ぶ*/
0020.00 pipe(fildes);
によって filedes[0] と fildes[1] を pipe で結ぶ。
詳しく説明すると pipe という関数(命令) は 2つの新しいファイル識別子を生成すると同時に
それら2つをリダイレクトして結合するのである。
つまり pipe は既存の 1組のファイル識別子を結合するのではなく、新たに空き番号のある
ファイル識別子を新規に作成して、それらを結合させるのである。
例えばファイル識別子は 1番はすでに使われていて 0 番と 2 番が空いているのであれば
pipe によって fildes[0] は 0 番、 fildes[1] は 2 番として割り振られます。
上記のサンプルの場合は初めて実行されるのだから、
fildes[0] = 0, fildes[1] = 1
となるだろう。
次に、
0023.00 if((bytesWritten = write(fildes[1], writeData, 10)) == FALSE){
によってAAA… が保管されている変数 writeData の 10バイトを fildes[1] に出力しておいてから
0029.00 if((bytesRead = read(fildes[0], readData, 10)) == FALSE){
によって fildes[0] を読み取ると readData には 先の AA … の文字列が入ります。
つまり fildes[1] に書き込まれた AAA … という文字列は fildes[0] を通じて
読み取られたことになる。
pipe 関数は結合された1組のファイル識別子を新しく生成する。
という基本を抑えておいて頂きたい。