---
title: pipe と socketpair
url: https://doc.liz6.com/ja/systems-programming/06-ipc-and-synchronization/02-pipes-and-socketpair
locale: ja
area: systems-programming
tags:
- systems-programming
- ipc-and-synchronization
date: 2026-06-30
modified: 2026-07-16
description: 'カバー: pipe → socketpair (AF_UNIX) → splice → pipe の容量 → AF_UNIX vs TCP → パフォーマンスの考慮事項 対象: Linux ユーザー空間 IPC'
---

# 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: 単方向パイプ

```c
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 の内部構造

```c
// 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: ゼロコピー転送

```c
// 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: 双方向パイプ

```c
#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

| | pipe | socketpair (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*
