- 作者: 塚越一雄
- 出版社/メーカー: 技術評論社
- 発売日: 2000/06
- メディア: 単行本
- 購入: 3人 クリック: 56回
- この商品を含むブログ (35件) を見る
前回はこちら
今回から名前付きパイプを使ったプロセス間通信についてまとめます。
前回までやっていた匿名パイプはファイルディスクリプタを介してパイプへデータを書込んだり、読み込んだりしていました。つまりパイプには名前がありませんでした。
今回からまとめる名前付きパイプはスペシャルファイルと呼ばれる特殊なファイルを介してデータをやりとりします。ファイルには当然名前があり、その名前を使用してデータを読み書きするので「名前付き」とわざわざ呼んでいるようです。
名前付きパイプを利用する方法としては以下の方法があります。
1. mknodコマンドを利用した方法
mknodというコマンドは名前付きパイプに限らず、スペシャルファイルを作成するためのコマンドです。
[itotto@itotto ]$ \ls -l 合計 8 drwxr-xr-x 2 itotto itotto 4096 11月20日 01:04 executable/ drwxr-xr-x 2 itotto itotto 4096 11月20日 01:04 source/ [itotto@itotto ]$ mknod named_pipe p [itotto@itotto ]$ \ls -l 合計 8 drwxr-xr-x 2 itotto itotto 4096 11月20日 01:04 executable/ prw-r--r-- 1 itotto itotto 0 11月21日 01:47 named_pipe| drwxr-xr-x 2 itotto itotto 4096 11月20日 01:04 source/ [itotto@itotto ]$
named_pipe という名前でファイルが作成されています。さらに詳しく見てみると
prw-r--r-- 1 itotto itotto 0 11月21日 01:47 named_pipe| ↑pというのがファイルの種類がパイプである事を示しています
となっています。ちなみに上記のファイル名の末尾に|が付いているのもパイプである事を示唆しています。
2. mkinfoコマンドを利用した方法
mkfifoはその名のとおり、fifoをmakeするコマンドです。つまりパイプ作成専用コマンドです。使い方はほとんどmknodと同じですが、専用コマンドですので引数を指定する必要がありません。
[itotto@itotto ]$ \ls -l 合計 8 drwxr-xr-x 2 itotto itotto 4096 11月20日 01:04 executable/ drwxr-xr-x 2 itotto itotto 4096 11月20日 01:04 source/ [itotto@itotto ]$ mkfifo named_pipe [itotto@itotto ]$ \ls -l 合計 8 drwxr-xr-x 2 itotto itotto 4096 11月20日 01:04 executable/ prw-r--r-- 1 itotto itotto 0 11月21日 01:47 named_pipe| drwxr-xr-x 2 itotto itotto 4096 11月20日 01:04 source/ [itotto@itotto ]$
3. システムコールを利用した方法
mknod()システムコールかもしくはmkfifo()関数を使用する。よく見たら上のコマンドと名前が一緒なので特に説明は要らなさそう。
/*** ノードを作成する ***/ // #include <unistd.h> // #include <sys/types.h> // #include <sys/stat.h> // #include <fcntl.h> // // 第一引数 pathname - ファイル名 // 第二引数 mode - 作成するノードの設定値 // 第三引数 dev - デバイスファイル以外は指定する必要なし // // 返却値 // 成功時 : 0 // 失敗時 : -1 int mknod(const char *pathname, mode_t mode, dev_t dev);
パイプ作成のサンプルは以下のとおりです。
1 #include <unistd.h> 2 #include <sys/stat.h> 3 #include <stdio.h> 4 5 #define FILENAME "/home/itotto/pg/c/named_pipe" 6 7 int main() 8 { 9 if (access(FILENAME, F_OK) == -1) 10 { 11 if (mknod(FILENAME, 0666 | S_IFIFO, 0) == -1) 12 { 13 perror("mknod()"); 14 return 1; 15 } 16 else 17 { 18 printf("パイプ(%s)を作成しました\n", FILENAME); 19 } 20 } 21 else 22 { 23 printf("パイプ(%s)は既に存在します\n", FILENAME); 24 } 25 26 return 0; 27 }
説明し忘れていましたが、access()はファイルのpermissionを取得するためのシステムコールです。これがファイルの有無チェックにも使用できるようです。
# ↓定義はこんな感じ
/*** ファイルのpermissionチェック ***/ // #include <unistd.h> // // 第一引数 pathname - ファイル名 // 第二引数 mode - permissionのbit pattern // // 返却値 // 許可されている : 0 // 許可されていない : -1 int access(const char *pathname, int mode);
ではプログラムを早速実行してみます。
[itotto@itotto ]$ \ls -l 合計 12 drwxr-xr-x 2 itotto itotto 4096 11月20日 01:04 executable/ -rw-r--r-- 1 itotto itotto 401 11月21日 02:19 mkmypipe.c drwxr-xr-x 2 itotto itotto 4096 11月20日 01:04 source/ [itotto@itotto ]$ gcc -o mkmypipe mkmypipe.c [itotto@itotto ]$ ./mkmypipe パイプ(/home/itotto/pg/c/named_pipe)を作成しました [itotto@itotto ]$ \ls -l 合計 20 drwxr-xr-x 2 itotto itotto 4096 11月20日 01:04 executable/ -rwxr-xr-x 1 itotto itotto 5300 11月21日 02:19 mkmypipe* -rw-r--r-- 1 itotto itotto 401 11月21日 02:19 mkmypipe.c prw-r--r-- 1 itotto itotto 0 11月21日 02:19 named_pipe| drwxr-xr-x 2 itotto itotto 4096 11月20日 01:04 source/ [itotto@itotto ]$ ./mkmypipe パイプ(/home/itotto/pg/c/named_pipe)は既に存在します [itotto@itotto ]$
ファイルの有無チェックも含めて正常に動作している事が分かります。
続いてパイプの使用方法について。入力側と読み取り側で別のコンソールが必要になるので、二つの端末を立ち上げてください。
まず、パイプと言ってますが、一見普通のファイルですので試しにデータを書き込んで見ます。
[端末1]
[itotto@itotto ]$ \ls -l 合計 8 drwxr-xr-x 2 itotto itotto 4096 11月21日 13:21 executable/ prw-r--r-- 1 itotto itotto 0 11月21日 02:19 named_pipe| drwxr-xr-x 2 itotto itotto 4096 11月21日 13:21 source/ [itotto@itotto ]$ echo I am itotto > named_pipe ↑ここで止まる
ファイルへ標準出力経由でデータをリダイレクトしたところで何も応答がなくなってしまいました。この状態でもう一つの端末を操作します。
[端末2]
[itotto@itotto ]$ \ls -l 合計 8 drwxr-xr-x 2 itotto itotto 4096 11月21日 13:21 executable/ prw-r--r-- 1 itotto itotto 0 11月21日 13:25 named_pipe| drwxr-xr-x 2 itotto itotto 4096 11月21日 13:21 source/ [itotto@itotto ]$ cat named_pipe I am itotto [itotto@itotto ]$
named_pipeの中をcatで覗いてみると、先ほど[端末1]でリダイレクトしたデータを読み取る事が出来ます。ここでもう一度[端末1]へ戻ってみると先ほど止まっていた場所から先に進んでいる事がわかります。
[端末1]
[itotto@itotto ]$ echo I am itotto > named_pipe ←さっきはここで止まってた [itotto@itotto ]$
名前付きパイプにデータを書き込んだ場合には、誰かにそれを受け取ってもらわない限り応答が返ってこなくなるようです。便利なような不便なような微妙な名前付きパイプ...。
次回はもっと便利に使いこなす方法をまとめます。