進程是作業系統中正在執行的程式實例,也是資源分配的最小單位。在我們日常運行的系統中,同時存在成百上千個進程默默工作,我們編寫的代碼經過編譯執行後,同樣會生成一個進程。一個進程由程式碼、數據、變量(佔用系統記憶體)、打開的文件(文件描述符)以及運行環境組成。Linux 系統為了優化資源利用,會在進程之間共享程式碼和系統函數庫,因此記憶體中始終只存在一份代碼副本。
鑑於進程的核心地位,本文將系統總結 Linux 進程的基礎知識,涵蓋創建、結構、調度與狀態等關鍵主題。
進程的誕生始於 fork() 系統調用。以下示例代碼展示了基本用法:
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
int main() {
pid_t pid;
char *msg;
int n;
printf("Fork program starting\n");
pid = fork(); // 創建子進程
// 父子進程均從此處繼續執行
switch (pid) {
case -1:
perror("Fork failed.");
exit(EXIT_FAILURE);
case 0: // 子進程
msg = "This is the child";
n = 2;
break;
default: // 父進程
msg = "This is the parent";
n = 3;
break;
}
for (; n > 0; --n) {
printf("%s\n", msg);
sleep(1);
}
exit(EXIT_SUCCESS);
}
fork() 返回 pid_t 類型值(本質是 int),其返回值決定進程身份:
父子進程雖從同一代碼位置繼續執行,但通過返回值區分身份,各自執行不同邏輯。這種「複製-分流」機制是 Unix/Linux 進程創建的核心特徵。

上圖展示了進程在記憶體中的結構,雖然編碼時不直接操作這些區域,但理解它們是掌握父子進程關係、記憶體共享與隔離的關鍵。後續許多進程相關問題的分析均以此為基礎。
單核處理器同一時刻只能執行一個進程,但我們感覺到多進程「同時」運行,是因為作業系統將 CPU 時間劃分為極短的時間片,快速切換進程產生並行假象。Linux 內核調度器基於進程優先級進行調度,優先級高的進程獲得更多運行機會。
wait() 讀取退出碼並釋放。SIGSTOP、SIGTSTP 等信號後暫停執行。| 狀態碼 | 含義 |
|---|---|
| R | 運行 |
| S | 中斷睡眠 |
| D | 不可中斷睡眠 |
| T | 停止 |
| Z | 僵死 |
此外還可能出現:W(無常駐頁面,舊內核)、<(高優先級)、N(低優先級)、L(記憶體鎖頁)。
僅等待 CPU 的進程稱為就緒進程,狀態標誌為 TASK_RUNNING。時間片用盡時,調度器剝奪 CPU 控制權,從運行隊列選擇下一個進程。
發送 SIGSTOP 會使進程進入 TASK_STOPPED(除非處於不可中斷睡眠);SIGCONT 可恢復至 TASK_RUNNING。
進程退出時進入 TASK_DEAD,資源被回收,僅保留 task_struct(含退出碼、統計信息),故稱「僵屍」。父進程調用 wait() 系列系統調用可獲取退出信息並釋放屍體。
內核在子進程退出時向父進程發送 SIGCHLD 信號通知「收屍」。若父進程先退出,子進程會被托管給進程組內下一個進程或 1 號進程,確保每個進程都有父進程。
製造僵屍進程的簡單代碼:
if (fork()) while(1) sleep(100);
父進程無限循環不調用 wait(),子進程退出後即成為僵屍。