- 作者: 塚越一雄
- 出版社/メーカー: 技術評論社
- 発売日: 2000/06
- メディア: 単行本
- 購入: 3人 クリック: 56回
- この商品を含むブログ (35件) を見る
前回はこちら
名前付きパイプの使用方法の続きです。今回は名前付きパイプを使用してプロセス間でデータを送受信するプログラムを作成します。
[受信用プログラム(receiver.c)]
1 /********************************************************* 2 * データ受信側プログラム(receiver.c) 3 *********************************************************/ 4 5 #include <unistd.h> 6 #include <sys/stat.h> 7 #include <fcntl.h> 8 #include <stdio.h> 9 10 #include "named_pipe.h" 11 12 int main() 13 { 14 int fifo, nbyte ; 15 char buff[BUFSIZ]; 16 17 /* パイプ用スペシャルファイルが無ければ作成する */ 18 if (access(MYNAMEDPIPE, F_OK) == -1) 19 { 20 if (mknod(MYNAMEDPIPE, 0666 | S_IFIFO, 0) == -1) 21 { 22 perror("mknod()"); 23 return 1; 24 } 25 else 26 { 27 printf("1. パイプ(%s)を作成しました\n", MYNAMEDPIPE); 28 } 29 } 30 else 31 { 32 printf("1. パイプ(%s)は既に存在します\n", MYNAMEDPIPE); 33 } 34 35 printf("receiver : データ待ち受け中...\n"); 36 37 /* 読取専用でパイプを開く */ 38 if ((fifo = open(MYNAMEDPIPE, O_RDONLY)) == -1) 39 { 40 perror("open()"); 41 unlink(MYNAMEDPIPE); 42 return 1; 43 } 44 45 /* パイプ経由で入ってきたデータを読取 */ 46 while ( (nbyte = read(fifo, buff, BUFSIZ)) > 0) 47 { 48 write(fileno(stdout), buff, nbyte); 49 } 50 51 close(fifo); 52 unlink(MYNAMEDPIPE); 53 54 if (nbyte == -1) 55 { 56 perror("write()"); 57 return 2; 58 } 59 60 return 0; 61 }
[送信用プログラム(sender.c)]
1 /********************************************************** 2 * データ送信側プログラム(sender.c) 3 **********************************************************/ 4 5 #include <unistd.h> 6 #include <fcntl.h> 7 #include <stdio.h> 8 9 #include "named_pipe.h" 10 11 int main() 12 { 13 int fifo, nbyte ; 14 char buff[BUFSIZ]; 15 16 /* 書込専用でパイプを開く */ 17 if ((fifo = open(MYNAMEDPIPE, O_WRONLY)) == -1) 18 { 19 perror("open()"); 20 return 1; 21 } 22 23 /* 標準入力からデータを読み込んでパイプへ書き込み */ 24 while((nbyte = read(fileno(stdin), buff, BUFSIZ)) > 0) 25 { 26 if (write(fifo, buff, nbyte) != nbyte) 27 { 28 perror("write()"); 29 close(fifo); 30 return 2; 31 } 32 } 33 34 if (close(fifo) == -1) 35 { 36 perror("close()"); 37 return 3; 38 } 39 40 return 0; 41 }
[ヘッダーファイル(named_pipe.h)]
1 #define MYNAMEDPIPE "/home/itotto/pg/c/named_pipe"
まずは受信用プログラム(receiver.c)を[端末1]で実行します。
[端末1]
[itotto@itotto ]$ gcc -o receiver receiver.c [itotto@itotto ]$ ./receiver 1. パイプ(/home/itotto/pg/c/named_pipe)を作成しました receiver : データ待ち受け中... ↑この状態でデータが来るまで待機します
続いて送信用プログラム(sender.c)を[端末2]で実行します。標準入力からデータを読み取って送信するように作っているので、シェルから実行したときにパイプ(シェルのパイプ機能)経由でls -alの結果を渡して見ます。
[端末2]
[itotto@itotto ]$ gcc -o sender sender.c [itotto@itotto ]$ ls -al | ./sender [itotto@itotto ]$
さて[端末1]に戻ってみると、ls -alの結果が表示されています。
[端末1]
[itotto@itotto ]$ ./receiver 1. パイプ(/home/itotto/pg/c/named_pipe)を作成しました receiver : データ待ち受け中... 合計 48 drwxr-xr-x 4 itotto itotto 4096 11月21日 22:15 ./ drwxr-xr-x 4 itotto itotto 4096 6月27日 21:57 ../ -rw-r--r-- 1 itotto itotto 14 11月15日 00:30 .vimrc drwxr-xr-x 2 itotto itotto 4096 11月21日 13:21 executable/ prw-r--r-- 1 itotto itotto 0 11月21日 22:15 named_pipe| -rw-r--r-- 1 itotto itotto 52 11月21日 14:20 named_pipe.h -rwxr-xr-x 1 itotto itotto 6260 11月21日 22:15 receiver* -rw-r--r-- 1 itotto itotto 1084 11月21日 20:51 receiver.c -rwxr-xr-x 1 itotto itotto 5505 11月21日 22:15 sender* -rw-r--r-- 1 itotto itotto 708 11月21日 20:50 sender.c drwxr-xr-x 3 itotto itotto 4096 11月21日 14:27 source/ [itotto@itotto ]$
これは[端末2]からパイプ経由で書き込まれたデータがあり、それが正しく表示されている事が分かります。これは前回コマンドレベルで確認したことと同じ事をプログラムで実装出来たといえます。
さて。ここまで名前付きパイプを使ってデータをやり取りする方法についてまとめてきました。その際に出てきた問題点として
-
- データを書き込んだ場合、それを読み取ってもらわない限りブロックされてしまう
- 読取側(receiver)を先に起動しておかないとエラーになる
1.についてはパイプを開く際(open())の第二引数 int flagsで O_NONBLOCKフラグかO_NDELAYフラグをorで指定するとノンブロッキングモード(non-blocking mode)でパイプを開く事が出来ます。ノンブロッキングモードって?という人には後で説明します。
2.についてはsender側の処理にパイプを作成する手順が抜けてるのが原因です。ちなみにエラーはこんな感じで出ます。
[itotto@itotto ]$ls -al | ./sender open(): No such file or directory [itotto@itotto ]$
これについてはソースを直します。
話を戻して。
ノンブロッキングモードについてですが、このモードは名前のとおり、処理がブロックされないモードです。つまり、前回receiverを実行した時のようにデータが送信されてくるのを待つような事はしません。つまりこのような動きになります。
>|sh| [itotto@itotto ]$ ./receiver 1. パイプ(/home/itotto/pg/c/named_pipe)を作成しました receiver : データ待ち受け中... [itotto@itotto ]$ ↑すぐにプロンプトに戻ります。
データが来るまでウェイトさせるのか、それとも受信側ではなく送信側を待たせるべきなのかどうかを判断し、受信側O_NONBLOCKフラグを立てるのかどうかを考えることが大事です。
匿名パイプや名前付きパイプについては今回で終了です。次回からはソケット通信についてまとめます。