海野秀之(うんのひでゆき)の外部記憶
Twitter (twilog) / RSS / アンテナ / ぶくま
% ls -l | less
みたいな場面で登場するパイプラインに対して、mkfifo なんかで明示的に作るパイプラインのことを、 named pipe とか言ったりすると思います。
じゃ、そうじゃないパイプライン (ls -l | less みたいなやつ) は名前の無いパイプラインなんだろうか。 それとも、ユーザが名前を意識してないだけ?
仕様として、どっかに書かれていないか調べたいんだけど、まずは実験してみよう。
コード:
#include <stdio.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <unistd.h> main() { struct stat buff; const char *const name = "hoge"; int fdes; if (fstat(STDIN_FILENO, &buff) == 0){ printf("stdin: dev=%d, nlink=%d\n", buff.st_dev, buff.st_nlink); } mkfifo(name, 0644); if (stat(name, &buff) == 0){ printf("named pipe: dev=%d, nlink=%d\n", buff.st_dev, buff.st_nlink); } fdes = open(name, O_RDONLY); unlink(name); if (fstat(fdes, &buff) == 0){ printf("named, but unlinked pipe: dev=%d, nlink=%d\n", buff.st_dev, buff.st_nlink); } close(fdes); }
実行例(1):
% ./a.out stdin: dev=11, nlink=1 named pipe: dev=64769, nlink=1 named, but unlinked pipe: dev=64769, nlink=0
実行例(2):
% echo hoge | ./a.out stdin: dev=6, nlink=1 named pipe: dev=64769, nlink=1 named, but unlinked pipe: dev=64769, nlink=0
このときの stdin が、問題のパイプライン。やっぱり nlink が 1 になっている。 つまり、ぼくが名前を知らないだけ、だと思えばいいのかな?
シェルのソースを読めってことか。そういや、bash のソースでコードリーディングの練習しようと思ってたんだった。 (zfs もね)
なお、実行例はいずれも CentOS 5 上にて。別途 named pipe になにか書いてやらないと、open が刺さるらしい。
ためしに、Solaris 10 上でコンパイルしようとしたら、
In function `main': 24: error: `O_ASYNC' が宣言されていません (この関数内で最初に利用) 24: error: (未宣言の各変数については、それが最初に現われたそれぞれの関数 24: error: に対して一度だけ報告されます。)
だってさ。要調査。
→ O_RDONLY に変えた。ってか、O_ASYNC が何かわかってない(笑)。
Solaris 10 でやってみた:
% ./a.out stdin: dev=90701824, nlink=1 named pipe: dev=67174447, nlink=1 named, but unlinked pipe: dev=67174447, nlink=0 % ls | ./a.out stdin: dev=92536832, nlink=0 named pipe: dev=67174447, nlink=1 named, but unlinked pipe: dev=67174447, nlink=0
おおおおおおおおおおおおおおおっ!!!!!!!!
ほんとに、unnamed (unlinked) だ!他人は何人たりとも触れないところ(おおげさ)に居る!
いやぁ、Linux と Solaris 見比べると面白いなぁ。
シェルの実装の違いだったりして。 /proc の仕様がちがうからって線もありそうだ(まったく確信・確証はない)。