1. 名前付きパイプの概念

名前付きパイプ(Named Pipe / FIFO) は、ファイルシステム上に名前を持つ特殊なファイルで、プロセス間でデータをやり取りするための仕組みです。

通常のパイプとの違い

# 通常のパイプ(無名パイプ)
ls | grep .txt
# ↑ lsの出力をgrepの入力に直接つなぐ(親子プロセス間のみ)

# 名前付きパイプ
mkfifo /tmp/mypipe  # ファイルシステム上に作成
ls > /tmp/mypipe &  # プロセス1が書き込み
cat < /tmp/mypipe   # プロセス2が読み込み(無関係なプロセス間でOK)

特徴

// 名前付きパイプの動作イメージ

// プロセスA(書き込み側)
FileOutputStream fos = new FileOutputStream("/tmp/mypipe");
fos.write("Hello".getBytes());  // ここでブロック(読み手が現れるまで)

// プロセスB(読み込み側)
FileInputStream fis = new FileInputStream("/tmp/mypipe");
int data = fis.read();  // プロセスAが書き込むまでブロック

重要な性質:

2. Windowsで名前付きパイプが使いにくい理由

Linux/Macの場合

# 簡単に作成できる
mkfifo /tmp/mypipe

# 通常のファイルのように扱える
echo "test" > /tmp/mypipe &
cat /tmp/mypipe

Windowsの場合

Windowsにも名前付きパイプはありますが...

// Windowsの名前付きパイプは特殊なAPI経由でしかアクセスできない
// 通常のFileInputStream/OutputStreamでは使えない!

// こんな形式になる
String pipeName = "\\\\.\\pipe\\mypipe";

// しかもWin32 APIを直接使う必要がある(JNAなど必要)

Windowsの名前付きパイプの問題点:

  1. パス形式が特殊: \\.\pipe\名前 という形式
  2. Java標準APIで扱えない: FileInputStreamでは開けない
  3. ネイティブライブラリが必要: JNAやJNIで Win32 API を呼ぶ必要がある

Windows名前付きパイプの実装例(参考)

// JNAライブラリを使った例(複雑!)
import com.sun.jna.platform.win32.Kernel32;
import com.sun.jna.platform.win32.WinNT;
import com.sun.jna.ptr.IntByReference;

public class WindowsNamedPipe {
    public static void main(String[] args) {
        // パイプ作成
        WinNT.HANDLE hPipe = Kernel32.INSTANCE.CreateNamedPipe(
            "\\\\.\\pipe\\mypipe",
            WinBase.PIPE_ACCESS_DUPLEX,
            WinBase.PIPE_TYPE_BYTE,
            1, 1024, 1024, 0, null
        );
        
        // 接続待ち
        Kernel32.INSTANCE.ConnectNamedPipe(hPipe, null);
        
        // データ送受信...
        // (さらに複雑なコードが続く)
    }
}

3. だからソケットを使う

ソケットは クロスプラットフォーム で、Java標準APIで簡単に使えます。

ソケットの利点

// どのOSでも同じコードで動く!

// サーバー側(送信側)
ServerSocket server = new ServerSocket(12345);
Socket client = server.accept();
OutputStream os = client.getOutputStream();
os.write("Hello".getBytes());

// クライアント側(受信側)
Socket socket = new Socket("localhost", 12345);
InputStream is = socket.getInputStream();
int data = is.read();

比較表

特徴 名前付きパイプ ソケット
Linux/Mac対応 ◎ 簡単 ◎ 簡単
Windows対応 △ 複雑 ◎ 簡単
Java標準API Linux/Macのみ 全OS
ネットワーク越し × 不可 ◎ 可能
同一マシン限定 ◎ 高速 △ やや遅い
セットアップ mkfifo必要 不要

4. 実際の使い分け

名前付きパイプを使うケース

# Linux/Macで同一マシン内の簡単な通信
mkfifo /tmp/log_pipe

# ログ収集など
./app1 > /tmp/log_pipe &
./app2 < /tmp/log_pipe

ソケットを使うケース

// クロスプラットフォーム
// ネットワーク越しの通信も可能
// より柔軟な実装

ServerSocket server = new ServerSocket(8080);
// どこからでも接続可能

まとめ

実際のプロジェクトでは、ソケット版の方が無難です!