進程與線程的核心區別在於內存共享程度。本文基於C程序四大內存分區模型,深度剖析進程隔離與線程共享的機制、性能影響及工程選型依據。
父進程內存空間 子進程內存空間 (fork後)
┌─────────────────┐ ┌─────────────────┐
│ 代碼區 (共享) │ ←─── │ 代碼區 (只讀共享)│
├─────────────────┤ ├─────────────────┤
│ 數據區 (私有) │ │ 數據區 (私有副本) │
├─────────────────┤ ├─────────────────┤
│ 堆區 (私有) │ │ 堆區 (私有副本) │
├─────────────────┤ ├─────────────────┤
│ 棧區 (私有) │ │ 棧區 (私有副本) │
└─────────────────┘ └─────────────────┘
關鍵特性:
fork()後父子進程映射同一物理代碼頁(Copy-on-Write機制)主進程內存空間
┌─────────────────┐
│ 代碼區 (共享) │ ← 所有線程共享
├─────────────────┤
│ 數據區 (共享) │ ← 全局/靜態變量共享
├─────────────────┤
│ 堆區 (共享) │ ← malloc/free 共享,需鎖保護
├─────────────────┤
│ 棧區 (私有) │ ← 每線程獨立棧(默認8MB)│
│ 線程1棧 │
│ 線程2棧 │
│ 線程N棧 │
└─────────────────┘
關鍵特性:
| 維度 | 進程 | 線程 |
|---|---|---|
| 地址空間 | 獨立虛擬地址空間 | 共享進程虛擬地址空間 |
| 代碼區 | 只讀共享(COW) | 完全共享 |
| 數據區 | 私有副本 | 完全共享 |
| 堆區 | 私有副本 | 完全共享 |
| 棧區 | 私有副本 | 各線程私有 |
| 通信方式 | IPC機制 | 共享內存+同步原語 |
| 創建開銷 | 高(毫秒級) | 低(微秒級) |
| 上下文切換 | 切換頁表、MMU刷新 | 僅切換寄存器、棧指針 |
| 穩定性 | 崩潰不影響其他進程 | 一線程崩潰導致全進程退出 |
| 資源佔用 | 獨立資源句柄表 | 共享進程資源句柄 |
nginx多worker)線程共享帶來便利的同時,引入並發風險:
volatile、內存屏障、C11原子類型malloc/free成為瓶頸 → 線程本地緩存分配器用戶態線程(協程)進一步降低開銷:
「進程隔離,線程共享」是作為系統程序員的核心直覺。理解內存佈局差異,能指導:
下一回將探討線程同步機制的內存語義基礎,敬請期待。