このページの目次

pipe と socketpair

カバー: pipe → socketpair (AF_UNIX) → splice → pipe の容量 → AF_UNIX vs TCP → パフォーマンスの考慮事項 対象: Linux ユーザー空間 IPC

概要

pipe と Unix ドメインソケットは、Linux 上で最も一般的なローカル IPC メカニズムです。pipe は単方向データストリーム(親プロセスと子プロセス間)に適しており、socketpair は双方向通信に適しています。正しい IPC を選択するには、それらのカーネル実装の違い(pipe は pipefs ベース、Unix ソケットは VFS + 独立したプロトコルスタックベース)を理解することが重要です。

pipe: 単方向パイプ

int pipefd[2];
pipe(pipefd);            // pipefd[0]=読み込み端, pipefd[1]=書き込み端

// または: pipe2(pipefd, O_NONBLOCK | O_CLOEXEC);

write(pipefd[1], buf, len);  // 書き込み
read(pipefd[0], buf, len);   // 読み込み

// デフォルトの pipe 容量: 16ページ (4KBページでは 64KB)
// 変更可能: fcntl(fd, F_SETPIPE_SZ, size)

pipe の内部構造

// fs/pipe.c
// 各 pipe = 1つの pipe_inode_info:
//   環状バッファ (デフォルト 16ページ)
//   リーダーがデータを待機 → wait queue に追加 → ライターが到着 → 起床
//   ライターが空き容量を待機 → wait queue に追加 → リーダーが到着 → 起床

// pipe の容量:
cat /proc/sys/fs/pipe-max-size  # 最大容量 (デフォルト 1MB)
fcntl(fd, F_SETPIPE_SZ, 1048576);  // 1MB に設定

splice: ゼロコピー転送

// splice は pipe の超能力:
//   ユーザー空間を経由しない → FD1 → pipe → FD2

// ファイル → ソケット (sendfile の基盤):
splice(file_fd, &offset, pipefd[1], NULL, size, 0);  // ファイル → pipe
splice(pipefd[0], NULL, sock_fd, NULL, size, 0);     // pipe → ソケット
// → ゼロコピー: データはページキャッシュから直接ソケットバッファへ

socketpair: 双方向パイプ

#include <sys/socket.h>
int sv[2];
socketpair(AF_UNIX, SOCK_STREAM, 0, sv);

// sv[0] ↔ sv[1] 双方向通信
write(sv[0], "hello", 5);
read(sv[1], buf, 5);     // "hello" を受信

// SOCK_STREAM: 信頼性あり, 順序保証, 双方向 (TCP に類似)
// SOCK_DGRAM:  信頼性なし, 境界保持 (UDP に類似)
// SOCK_SEQPACKET: 信頼性あり + 境界保持 (5.3以降)

AF_UNIX ソケット vs TCP

同一マシン上のプロセス間通信:
  AF_UNIX ソケット (Unix ドメイン):
    プロトコルスタックを経由しない → カーネル内で sk_buff のみを渡す
    レイテンシ: ~2μs (TCP localhost は ~10μs)
    スループット: ~5GB/s (TCP localhost は ~2GB/s)

  AF_UNIX が高速な理由:
    1. TCP ステートマシンがない (SYN/SYN-ACK/FIN がない)
    2. チェックサムなし (ローカル通信では不要)
    3. フロー制御/輻輳制御なし
    4. IP 断片化/再構築なし

  AF_UNIX の資格情報伝送 (SCM_CREDENTIALS):
    sendmsg(sock, msg, 0)  ← pid/uid/gid を付随
    受信側: recvmsg → SCM_CREDENTIALS → 送信者の身元を信頼
    → DBus, systemd, polkit はこれに依存している

pipe vs socketpair vs eventfd

pipesocketpair (AF_UNIX)eventfd
方向単方向双方向単方向シグナル
データバイトストリームバイトストリーム/メッセージ8バイトカウンター
容量64KB+send バッファ (デフォルト 200KB)1カウンター
spliceサポートありサポートなし (4.x以降一部サポート)サポートなし
資格情報伝送なしあり (SCM_CREDENTIALS)なし
epollサポートありサポートありサポートあり

参考

  • man: pipe(2), socketpair(2), splice(2), unix(7)
  • ソースコード⁠: fs/pipe.c, net/unix/af_unix.c

キーワード: pipe, socketpair, AF_UNIX, splice, SCM_CREDENTIALS, pipe capacity, eventfd