03-1. IPC 概述

⏱️ 閱讀時間: 8 分鐘 🎯 難度: ⭐⭐ (簡單)


🤔 什麼是 IPC?

IPC (Inter-Process Communication) = 進程間通訊

一句話解釋: 讓不同的 Process 能夠互相傳遞資料和訊息的機制。


🏢 用公司來比喻

公司 A(Process A)        公司 B(Process B)
├─ 辦公室 A                ├─ 辦公室 B
├─ 獨立資源                ├─ 獨立資源
└─ 員工                    └─ 員工

問題:兩家公司如何溝通?

IPC 機制 = 公司間的溝通方式:

  • 📞 Pipe = 電話專線
  • 📨 Message Queue = 郵件系統
  • 📂 Shared Memory = 共用雲端硬碟
  • 🌐 Socket = 網路會議

📋 IPC 的五種主要方式

1. Pipe(管道)

特性:

  • 單向通訊(A → B)
  • 半雙工(需要兩個 Pipe 才能雙向)
  • 適合父子 Process
from multiprocessing import Process, Pipe

def sender(conn):
    conn.send("你好,這是 Process A")
    conn.close()

def receiver(conn):
    msg = conn.recv()
    print(f"收到訊息: {msg}")
    conn.close()

# 創建 Pipe
parent_conn, child_conn = Pipe()

p1 = Process(target=sender, args=(parent_conn,))
p2 = Process(target=receiver, args=(child_conn,))

p1.start()
p2.start()
p1.join()
p2.join()

2. Message Queue(消息佇列)

特性:

  • 雙向通訊
  • 先進先出(FIFO)
  • 可以有多個生產者和消費者
from multiprocessing import Process, Queue

def producer(queue):
    for i in range(5):
        queue.put(f"資料 {i}")
        print(f"生產: 資料 {i}")

def consumer(queue):
    while True:
        try:
            msg = queue.get(timeout=1)
            print(f"消費: {msg}")
        except:
            break

queue = Queue()

p1 = Process(target=producer, args=(queue,))
p2 = Process(target=consumer, args=(queue,))

p1.start()
p2.start()
p1.join()
p2.join()

3. Shared Memory(共享記憶體)

特性:

  • 最快的 IPC 方式
  • 需要同步機制(Lock)
  • 適合大量資料交換
from multiprocessing import Process, Value, Array

def increment(shared_value, shared_array):
    shared_value.value += 1
    for i in range(len(shared_array)):
        shared_array[i] *= 2

# 創建共享記憶體
shared_value = Value('i', 0)  # 整數
shared_array = Array('i', [1, 2, 3, 4, 5])  # 陣列

p = Process(target=increment, args=(shared_value, shared_array))
p.start()
p.join()

print(f"Value: {shared_value.value}")
print(f"Array: {list(shared_array)}")

4. Socket(網路通訊)

特性:

  • 可以跨網路通訊
  • 支援 TCP/UDP
  • 最靈活的 IPC 方式
# Server Process
import socket

def server():
    s = socket.socket()
    s.bind(('localhost', 8888))
    s.listen(1)
    conn, addr = s.accept()
    msg = conn.recv(1024)
    print(f"收到: {msg.decode()}")
    conn.close()

# Client Process
def client():
    s = socket.socket()
    s.connect(('localhost', 8888))
    s.send(b"Hello from client")
    s.close()

5. Signal(信號)

特性:

  • 異步通知機制
  • 用於簡單的事件通知
import signal
import os
import time

def signal_handler(signum, frame):
    print("收到信號!")

# 註冊信號處理器
signal.signal(signal.SIGUSR1, signal_handler)

print(f"PID: {os.getpid()}")

# 發送信號給自己
os.kill(os.getpid(), signal.SIGUSR1)

time.sleep(1)

📊 IPC 方式對比

方式速度複雜度適用場景
Pipe父子 Process
Message Queue生產者/消費者
Shared Memory最快大量資料交換
Socket跨網路通訊
Signal事件通知

🎯 選擇建議

需要通訊的 Process 關係?
├─ 父子關係 → Pipe
├─ 大量資料 → Shared Memory
├─ 佇列模式 → Message Queue
├─ 跨機器 → Socket
└─ 簡單通知 → Signal

下一篇: 03-2. Pipe(管道)


最後更新:2025-01-04

0%