進程概念 (Process Concept)
本系列文章內容參考自經典教材 Operating System Concepts, 10th Edition (Silberschatz, Galvin, Gagne)。本文對應章節:Section 3.1 Process Concept。
早期電腦一次只能執行一支程式,該程式完全掌控所有系統資源。現代電腦系統則允許多支程式同時載入記憶體並發執行,這個演進要求作業系統對每支程式的執行行為有更嚴格的管控與隔離,因此催生了「進程(Process)」這個核心概念。進程是現代電腦系統中工作的基本單位,而 OS 的核心任務之一就是管理這些進程的生命週期。
3.1.1 進程 (The Process)
進程的記憶體佈局
進程是一支正在執行的程式(a program in execution)。一支程式從磁碟載入記憶體並開始執行後,便成為一個進程。進程的執行狀態由兩個關鍵資訊表示:程式計數器(Program Counter) 的當前值,以及所有處理器暫存器(CPU Registers) 的內容。
進程在記憶體中的佈局通常劃分為四個區段(Sections):
各區段說明如下:
| 區段 | 說明 | 大小 |
|---|---|---|
| Text Section | 可執行的程式碼本體 | 固定 |
| Data Section | 全域變數(Global Variables) | 固定 |
| Heap Section | 執行期間動態配置的記憶體(malloc/new) | 動態 |
| Stack Section | 函式呼叫的暫存資料(參數、區域變數、返回位址) | 動態 |
Text Section 與 Data Section 的大小在編譯時就已確定,執行過程中不會改變。Heap 與 Stack 則不同:
- Stack:每次發出函式呼叫,OS 就在 Stack 頂端壓入一筆 Activation Record(包含函式參數、區域變數、返回位址);函式返回時,這筆記錄被彈出。Stack 因此呈 LIFO(Last In, First Out)的堆疊結構,向低位址方向(圖中向下)成長。
- Heap:當程式動態配置記憶體時(例如 C 的
malloc、C++ 的new),Heap 向高位址方向(圖中向上)延伸;free/delete時則收縮。
Stack 從高位址向下長,Heap 從低位址向上長,兩者共享中間的空閒區間(Free Space)。OS 必須確保這兩個區段不會相互覆蓋,否則會導致記憶體損毀(Memory Corruption)。
C 程式的記憶體佈局細節
Figure 3.1 呈現的是通用的進程記憶體模型;套用到實際的 C 程式時,佈局會更細一些,如下圖所示:
與圖 3.1 的主要差異有兩點:
-
Data Section 細分為兩個子區段:
- Initialized Data:已明確賦初值的全域/靜態變數(例如
int y = 15;) - Uninitialized Data(BSS):宣告但未賦值的全域/靜態變數(例如
int x;)。BSS 是歷史術語,全名為 block started by symbol,OS 在程式啟動時會自動將此區段清零。
- Initialized Data:已明確賦初值的全域/靜態變數(例如
-
argc/argv有獨立的區段:傳入main()的命令列參數存放於 Stack 頂端(高位址端),位置在一般區域變數之上。
GNU size 命令可查看各區段的實際大小(bytes):
text data bss dec hex filename
1158 284 8 1450 5aa memory
其中 data 對應 Initialized Data(已賦值的全域變數,如 int y = 15),bss 對應 Uninitialized Data(未賦值的全域變數,如 int x),dec 與 hex 是三個區段的位元組總和。