UNIX/Linuxのパイプ

20年くらい日々使っていながら、UNIX/Linuxのパイプの振る舞いをよく分かってませんでした。『易経』に「日に用いて知らず」というのはこれです。ちょっと簡単なコードで実験してみました。

リスト1 test1.c

#include <stdio.h>

int main(void)
{
	int i;
	
	for(i=0;i<5;i++){
		sleep(1);
		printf("test1(%d)\n",i);
		fflush(stdout); // ←これが大事
	}
	
	return 0;
}

リスト2 test2.c

#include <stdio.h>

int main(void)
{
	char buff[1024];
	
	printf("test2 starts.\n");
	
	while(gets(buff)!=NULL){
		printf("test2[%s]\n",buff);
	}
	
	return 0;
}

実行結果

$ gcc test1.c -o test1
$ gcc test2.c -o test2
$ ./test1 | ./test2
test2 starts.  ← 0秒後
test2[test1(0)] ← 1秒後
test2[test1(1)] ← 2秒後
test2[test1(2)] ← 3秒後
test2[test1(3)] ← 4秒後
test2[test1(4)] ← 5秒後 
$        ← 5秒で終了

つまり

test1とtest2はパラレルに動いてて、test2のgetsが標準入力(=test1の標準出力)を同期待ちしてるんですね。