Transcript fd[0]

パイプライン通信
パイプライン通信












標準入出力とパイプライン
シェルとパイプライン
パイプによるプロセス間通信の仕組み
pipeシステム・コール
pipeシステム・コールとプロセス間通信
pipeシステム・コールと、ファイル識別子
パイプread/writeプログラミング
パイプライン通信プログラミング
コマンドパイプライン型通信プログラミング
dupシス テム・コール
dupシス テム・コールと、ファイル識別子
パイプdupeプログラミング
パイプライン通信
標準入出力とパイプライン





cmd < file

fileをcmdの標準入力にする
標準入力

キーボード

ファイル
cmd > file

cmdの標準出力をfileにする
標準出力

ディスプレイ

ファイル
|: パイプライン

(前のコマンドの標準出力を
後のコマンドの標準入力に
する)
$ cat > input
ooki
oida
okajima
$ tr o i < input
iiki
iida
ikajima
$ tr o i < input > output
$ cat output
iiki
iida
ikajima
$ tr o i < input | sort > output
$ cat output
iida
iiki
ikajima
$
パイプライン通信
シェルとパイプライン

シェルで、次のようなプログラムを動
かすこと考える。



echo



tr
% echo "hello,world" | tr '[a-z]'
'[A-Z]'
HELLO,WORLD
%
write()

|
この例では、echo のプロセスと、tr の
プロセスは、パイプで接続されている。
パイプは、open() したファイルと同じよ
うにread() したり write() したり するこ
とがでる。
しかし実際には、ファイルではなく、プ
ロセスとプロセスが データを交換する
仕組(プロセス間通信の仕組)の1つ
である。
片方のプロセ スが write() したデータ
を、もう片方のプロセスがread() でき
る。
read()
パイプライン通信
パイプによるプロセス間通信の仕組み


パイプにより提供されるプロセス間通信
のサービスは、 (単方向の)ストリームと
も呼ばれる。
FIFO (First In, First Out)や Queue (待ち
行列) と呼ばれることもある。
echo
write()

|
tr
read()
パイプは、内部的には、8k バイト程度の
バッファ(メモリ)がオペレーティング・シス
テ ムのカーネルにある。

バッファが一杯になると、書込み側
のプロセスは write() で止まる
(write() システムコールの呼び出し
が元にもどらない。)

バッファが空だと、read() で止まる。

全部の書込み側の口が close() され
ると、read() で EOF が返る。
FIFO (First In, First Out)
Queue
パイプライン通信
pipeシステム・コール






パイプを作るには、pipe() システ
ム・コールを使う。
1つのパイプに対して、2つの
ファイル記述子(読込み用と書込
み用)が返される。
インクルードファイル
 #include <unistd.h>
書式
 int pipe(int filedes[2]);
戻値
 成功時 0
 失敗時 -1
使用例
 int fd[2];
 pipe(fd);
プロセス
fd[0]
pipe(fd);
fd[0]
=3
read用
fd[1]
=4
fd[1]
write用
パイプ
バッファ
パイプライン通信
pipeシステム・コールと、プロセス間通信
プロセスA
pipe(fd);
fd[0]
プロセスB
read用
write用
read用
pipe(fd);
fd[1]
fd[0]
パイプバッファ
write用
fd[1]
パイプライン通信
pipeシステム・コールと、ファイル識別子(1/3)
パイプライン通信
pipeシステム・コールと、ファイル識別子(2/3)
パイプライン通信
pipeシステム・コールと、ファイル識別子(3/3)
パイプライン通信
パイプread/write (1/2)
プロセス
fd[0]
pipe(fd);
fd[0]
=3
read用
fd[1]
=4
fd[1]
write用
パイプ
バッファ
パイプライン通信
パイプread/write (2/2)
pipe-self.c
パイプライン通信
パイプライン通信 (1/2)
プロセスA
プロセスB
read用
pipe(fd);
write用
fd[0]
read用
pipe(fd);
fd[1]
fd[0]
パイプバッファ
write用
fd[1]
パイプライン通信
パイプライン通信 (2/2)


pipe-processes.c
親プロセスは、パイプの読込み側(fildes[0])を閉じる。 そ
して、文字列から1バイトずつ取り出し、0 が現れるまで、
パイプの書込み側(fildes[1])に書込む。
子プロセスは、パイプの書込み側(fildes[1])を閉じる。 そ
してパイプの読込み側(fildes[0])から1バイト取り出す。こ
れをtoupper() で大文字に変換して、標準出力(1)に書き
出す。
パイプライン通信
コマンド型パイプライン通信 (1/3)
プロセスA
pipe(fd);
fd[0]
プロセスB
read用
write用
read用
pipe(fd);
fd[1]
fd[0]
パイプバッファ
write用
fd[1]
パイプライン通信
コマンド型パイプライン通信 (2/3)
parent.c
親プロセス
1. パイプラインを生成
2. 標準入力から数字を入力
3. 子プロセスchildを生成
4. パイプラインに数字を書込む
5. 子プロセス終了後パイプラインを
読む
6. 読み出した数値を出力
パイプライン通信
コマンド型パイプライン通信 (3/3)
child.c
子プロセス
1. 引数からファイルディスクリプタを得る
2. パイプラインから数字を読む
3. 数字を2乗する
4. 2乗した結果をパイプラインに書き込む
$ gcc -o parent parent.c
$ gcc -o child child.c
$ ./parent
512
512 x 512 = 262144
$
パイプライン通信
dupeシステム・コール



pipe() システム・コールで
作られたファイル記述子
は、しばしば dup() シス
テム・コールで、0, 1 に変
えられる。
dup() システム・コールは、
ファイル記述子を コピー
するものである。
dup() システム・コールは、
ファイル記述子を、小さ
い数字から探していくの
で、たとえば close(0) の
直後に dup(fd) すると、fd
が 0 にコピーされる。
標準出力をパイプに
切替
close( 1 );
dup( fildes[1] );
標準入力をパイプに
切替
close( 0 );
dup( fildes[0] );
パイプライン通信
dupeシステム・コールと、ファイル識別子
標準出力
をパイプに
切替
標準入力
をパイプに
切替
パイプライン通信
パイプdupeプログラミング
pipe-dupe-processes.c