Unixのパイプをmkfifo()で作ってdup2()で標準出力にコピーして書き込む

linux

パイプとは

Unixでプロセス間通信するためのもの。シェルで使う|は無名パイプ。 mkfifo()システムコールで名前付きパイプを作成でき、これを読み書きすることで任意のプロセス間でやりとりできる。

$ mkfifo hoge
$ ls -lh
$ prw-r--r-- ... 0B ... hoge

通常のファイルと同様に読み書きすることができ、読み書きどちらかを行おうとすると待つことになる。

$ echo hoge & # 読まれるまで待つ
$ cat hoge
aaaaa
[1]+  Done                    echo "aaaaa" > hoge

$ cat hoge & # 書かれるまで待つ
$ echo "bbbbb" > hoge
bbbbb
[1]+  Done                    cat hoge

ファイルディスクリプタをコピーするシステムコールdup2()でopenしたパイプを標準出力(1)にコピーしてみる。

#include <stdio.h>
#include <fcntl.h>

int main(){
  int fd = open("./hoge", O_WRONLY);
  if(fd < 0){
    printf("fail to open\n");
    return 1;
  }

  printf("OPEN %d \n", fd);

  if(dup2(fd, 1) < 0){
    printf("fail to dup2\n");
    return 2;
  }

  printf("WRITE\n"); // これがどこに書き込まれるか

  close(fd);
}

最後のprintfの内容は標準出力ではなく、パイプに書き込まれていることがわかる。

$ ./a.out &
$ echo "read `cat hoge` from pipe"
OPEN 3 
read WRITE from pipe

参考

パイプ (コンピュータ) - Wikipedia

mkfifoコマンドって使ってますか? - Qiita

リダイレクトの挙動 - Qiita