IPC 程序間通訊
## IPC(Inter-Process Communication,程序間通訊)概念
IPC 是讓**不同程序(Process)彼此交換資料、同步狀態或協調工作**的機制。
由於每個程序通常擁有獨立的虛擬記憶體空間,不能直接讀寫其他程序的變數,因此需要透過作業系統提供的 IPC 機制進行通訊。
IPC 通常涉及兩個目的:
1. **資料交換**:例如一個程序將資料傳送給另一個程序。
2. **程序同步**:例如等待某個程序完成、控制存取順序或避免資料競爭。
---
## 常見 IPC 方式比較
| IPC 方式 | 主要特性 | 通訊範圍 | 資料傳遞方式 | 優點 | 缺點/注意事項 |
|---|---|---|---|---|---|
| **PIPE** | 未命名管線,通常用於有親緣關係的程序 | 同一台主機,通常是父子程序 | 核心提供的位元組串流 | 簡單、使用方便、支援阻塞式讀寫 | 通常只能單向傳輸;只能由相關程序使用;沒有訊息邊界 |
| **FIFO** | 命名管線,也稱 Named Pipe | 同一台主機,不必有親緣關係 | 位元組串流 | 可讓無親緣關係程序通訊;介面簡單 | 只能在本機使用;通常是單向;開啟與關閉時要注意阻塞 |
| **Shared Memory** | 多個程序共享同一段記憶體 | 同一台主機 | 直接讀寫共享記憶體 | 速度最快、資料複製成本低,適合大量資料 | 必須搭配同步機制;容易產生競爭條件與資料不一致 |
| **Socket** | 透過 Socket 端點通訊 | 本機或跨網路 | 串流或訊息,依 Socket 類型而定 | 彈性高、支援網路、可建立 Client/Server 架構 | 相較本機記憶體或管線,協定與管理較複雜;需處理連線與錯誤 |
---
# 1. PIPE(匿名管線)
## 概念
PIPE 是由核心建立的一段通訊通道,資料通常遵循:
> 先寫入,後讀出;先進先出(FIFO,First In First Out)
典型使用方式是讓父程序與子程序溝通,例如 Shell 中的:
```bash
ls | grep ".txt"
```
其中:
- `ls` 將輸出寫入 PIPE
- `grep` 從 PIPE 讀取資料
## 特性
- 通常是**單向通訊**
- 多用於**具有親緣關係的程序**
- 父程序與子程序
- 兄弟程序
- 使用檔案描述元(file descriptor)讀寫
- PIPE 本身不保存永久資料
- 讀寫通常具備阻塞特性:
- PIPE 沒有資料時,讀取端可能阻塞
- PIPE 緩衝區滿時,寫入端可能阻塞
- 傳遞的是**位元組串流**,沒有內建的訊息邊界
## 優點
- API 簡單
- 核心負責同步部分讀寫操作
- 適合程序串接與串流資料處理
## 限制
- 不適合無親緣關係的程序
- 通常需要建立兩條 PIPE 才能實現雙向通訊
- 若需要區分不同訊息,必須由應用程式自行設計格式
---
# 2. FIFO(命名管線)
## 概念
FIFO 是具有名稱的管線,會在檔案系統中出現一個特殊檔案。不同程序只要知道這個路徑,就能開啟它進行通訊,不需要具有父子關係。
例如:
```text
/tmp/my_fifo
```
程序 A 寫入 FIFO,程序 B 從 FIFO 讀取。
## 特性
- 也是以**先進先出**方式傳遞資料
- 同一台主機上的程序可以使用
- 不要求程序具有親緣關係
- 本質上仍是**位元組串流**
- 通常為單向通訊
- 開啟 FIFO 時可能發生阻塞:
- 讀取端等待寫入端
- 寫入端等待讀取端
- FIFO 檔案本身只代表通訊端點,資料不會永久儲存在檔案中
## 優點
- 比匿名 PIPE 更有彈性
- 適合獨立啟動的程序互相溝通
- 操作方式類似一般檔案
## 限制
- 只能在同一台主機上使用
- 不適合大量資料或複雜的雙向通訊
- 若沒有程序讀取或寫入,另一端可能被阻塞
---
# 3. Shared Memory(共享記憶體)
## 概念
Shared Memory 會讓多個程序將同一段實體記憶體映射到各自的虛擬位址空間。之後,程序可以直接讀寫這段共同區域。
示意:
```text
程序 A 的位址空間 ─┐
├── 共享記憶體區域
程序 B 的位址空間 ─┘
```
它不像 PIPE 或 Socket 那樣需要一方「寫入」、另一方「讀取」系統緩衝區,而是直接存取共享資料。
## 特性
- 通訊速度通常最快
- 適合傳送大量資料
- 多個程序可以同時存取同一區域
- 需要額外的同步機制,例如:
- Semaphore
- Mutex
- Condition Variable
- Event
- 必須自行設計:
- 資料格式
- 讀寫狀態
- 緩衝區管理
- 生產者與消費者同步
## 優點
- 資料複製次數少
- 傳輸效率高
- 適合影像、音訊、大型資料結構等大量資料
## 限制與風險
- 若兩個程序同時修改資料,可能產生**競爭條件**
- 若缺乏同步,可能讀到不完整或不一致的資料
- 程序結束後,共享記憶體資源可能需要額外清理
- 設計難度通常高於 PIPE 或 Socket
## 重要觀念
Shared Memory 負責的是:
> 「共享資料」
但不負責:
> 「控制誰何時讀寫」
因此通常必須搭配 Semaphore 或其他同步工具。
---
# 4. Socket
## 概念
Socket 是一種通用的通訊端點,可以讓程序在本機或不同主機之間傳輸資料。
常見類型包括:
- **TCP Socket**
- 可靠
- 有連線
- 保證資料順序
- 適合檔案傳輸、HTTP、資料庫連線
- **UDP Socket**
- 無連線
- 傳輸速度快、延遲低
- 不保證送達與順序
- 適合即時影音、廣播或簡單查詢
- **Unix Domain Socket**
- 只用於同一台主機
- 通常比 TCP Loopback 更適合本機程序通訊
- 支援串流或資料報形式
## 特性
- 可支援本機程序通訊
- 可支援跨主機網路通訊
- 常採用 Client/Server 架構
- 可進行雙向通訊
- 可以處理串流或訊息型態,取決於 Socket 類型
- 需要處理:
- 建立連線
- 位址與連接埠
- 傳送與接收
- 連線中斷
- 網路錯誤
- 封包或訊息格式
## 優點
- 彈性最大
- 可跨程序、跨主機使用
- 支援多種通訊模型
- 適合服務導向架構與分散式系統
## 限制
- 程式設計較複雜
- 通常有較高的協定與資料複製成本
- TCP 是位元組串流,不保證一次 `send()` 對應一次 `recv()`
- 應用程式必須自行定義訊息邊界,例如:
- 固定長度
- 長度前綴
- 分隔符號
- 序列化格式
---
## 四種 IPC 的選擇建議
### 使用 PIPE
適合:
- 父子程序
- Shell 指令串接
- 簡單的單向串流資料
### 使用 FIFO
適合:
- 無親緣關係的本機程序
- 簡單的背景程序通知
- 不需要網路通訊的場景
### 使用 Shared Memory
適合:
- 大量資料傳輸
- 追求極高效能
- 影像、音訊、共享緩衝區
- 可以自行處理同步的系統
### 使用 Socket
適合:
- Client/Server 系統
- 跨主機通訊
- 微服務與分散式系統
- 需要雙向、長時間連線的程序
---
## 簡單比較
| 項目 | PIPE | FIFO | Shared Memory | Socket |
|---|---|---|---|---|
| 通訊範圍 | 本機 | 本機 | 本機 | 本機或跨網路 |
| 是否需親緣關係 | 通常需要 | 不需要 | 不需要 | 不需要 |
| 通訊方向 | 通常單向 | 通常單向 | 雙向 | 通常雙向 |
| 傳輸速度 | 中等 | 中等 | 快 | 視協定而定 |
| 是否需要同步 | 部分由核心處理 | 部分由核心處理 | 必須額外同步 | 需處理連線與協定 |
| 資料型態 | 位元組串流 | 位元組串流 | 共享資料結構 | 串流或資料報 |
| 跨主機 | 否 | 否 | 否 | 是 |
| 實作難度 | 低 | 低至中 | 中至高 | 中至高 |
總結來說:
- **PIPE/FIFO**:簡單的程序串流通訊
- **Shared Memory**:本機最快的大量資料共享
- **Socket**:最具彈性,可支援跨網路與 Client/Server 架構
相關學習地圖、教學課程
C 語言,系統程式