Windows XP Windows 7 Windows 2003 Windows Vista Windows 綜合教學 Linux 系統教學
Windows 10 Windows 8 Windows 2008 Windows NT Windows Server 電腦軟體教學
您现在的位置: Windows教程網 >> Windows教程 >  >> Linux 系統教學 >> 關於 Linux

Linux 進程核心知識體系:從 fork/exec 到僵屍/孤兒進程全解析

編輯:關於 Linux

進程是作業系統資源分配與調度的基本單位。理解 Linux 進程生命週期、創建機制 (fork/exec)、父子關係、終止回收、線程實現,是系統編程、性能調優、故障診斷的基石。本文構建完整知識圖譜。

一、程序 vs 進程:靜態與動態

  • 程序:磁盤上可執行文件 (ELF 格式),包含代碼段、數據段、符號表。靜態實體。
  • 進程:程序的一次執行實例。擁有獨立虛擬地址空間 (代碼、堆、棧、庫映射)、PCB (task_struct)、文件描述符表、信號處理表、內核棧。動態實體。
  • 同一程序可啟動多進程 (如 nginx master + 多 worker),相互隔離。

二、進程創建:fork() + exec() 雙重奏

1. fork():複製父進程

  • 系統調用,創建子進程,幾乎完整複製父進程地址空間 (頁表項指向同一物理頁,COW 複製時寫)、文件描述符表 (引用計數+1)、信號處理、環境變量。
  • 返回值:父進程得子 PID,子進程得 0。以此區分執行邏輯。
  • 失敗返回 -1 (EAGAIN: 進程數達限/內存不足; ENOMEM)。

2. exec() 族:載入新程序替換當前映像

  • execl, execv, execlp, execvp, execle, execve (l=列表, v=向量, p=PATH搜索, e=環境變量)。
  • 不創建新進程,替換 當前進程的代碼段、數據段、堆、棧,PID 不變,文件描述符默認保留 (除 FD_CLOEXEC)。
  • 成功不返回,失敗返回 -1。

3. 典型模式:Shell 啟動命令

// Shell 進程
pid = fork();
if (pid == 0) {          // 子進程
    execvp("ls", {"ls", "-l", NULL});
    perror("exec failed"); // exec 失敗才執行這裡
    _exit(1);
} else if (pid > 0) {    // 父進程
    waitpid(pid, &status, 0); // 回收子進程
} else {
    perror("fork failed");
}

三、進程標識與屬級關係

  • PID:進程唯一標識 (1..32768 默認,/proc/sys/kernel/pid_max 可調)。
  • PPID:父進程 PID。所有進程構成以 PID 1 (systemd/init) 為根的樹。
  • PGID:進程組 ID,等於組長進程 PID。用於作業控制、信號分發。
  • SID:會話 ID,等於會話首進程 PID。控制終端關聯。
  • UID/EUID, GID/EGID:實際/有效用戶/組 ID,決定權限。

查看:ps -eo pid,ppid,pgid,sid,uid,euid,cmd、pstree -p、cat /proc/PID/status。

四、進程終止與回收:避免僵屍與孤兒

1. 正常終止

  • exit(n) / return n (main) / _exit(n) (直接系統調用,不刷緩衝區/調用 atexit)。
  • 內核釋放資源 (內存、FD、鎖),保留退出碼、資源使用統計 於 PCB 中,進入 EXIT_ZOMBIE 狀態,向父進程發送 SIGCHLD。

2. 父進程回收 (wait 族)

  • wait(&status):阻塞等待任意子進程終止,回收 PCB,獲取退出信息。
  • waitpid(pid, &status, options):指定 PID、非阻塞 (WNOHANG)、支持作業控制。
  • waitid():更現代、靈活。

3. 僵屍進程

原因:子進程終止,父進程未調用 wait 回收。PCB 殘留佔用 PID、內核內存。ps 顯示 Z 狀態 (defunct)。

危害:大量僵屍耗盡 PID 池,導致無法創建新進程。

清理:殺死父進程 → 子進程成為孤兒 → 被 init (PID 1) 收養 → init 循環 wait 清理。或重啟系統。

4. 孤兒進程

原因:父進程先於子進程終止。

歸宿:內核將其 PPID 設置為 1 (init/systemd) 或子再啟動器 (subreaper, prctl(PR_SET_CHILD_SUBREAPER))。init 負責回收,無害。

五、線程:Linux 的特殊進程

  • Linux 無原生線程概念,線程 = 共享地址空間的進程 (LWP, Light Weight Process)。
  • clone() 系統調用:CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND | CLONE_THREAD 創建線程。
  • 共享:堆、全局變量、文件描述符表、信號處理、當前目錄。
  • 私有:棧 (默認 8MB)、寄存器、TLS (線程局部存儲)、errno、信號屏蔽字。
  • 調度單位是線程 (task_struct),進程只是資源容器。
  • PID = 線程組長 TID (TGID),getpid() 返回 TGID,gettid() 返回內核 TID。

六、/proc 文件系統:進程運行時窗口

/proc/PID/
├── cmdline      # 啟動命令行 (空格用 \0 分隔)
├── environ      # 環境變量 (\0 分隔)
├── fd/          # 文件描述符符號鏈接
├── maps         # 內存映射區域
├── status       # 狀態信息 (State, PPid, Uid, VmRSS, Threads...)
├── stat         # 統計信息 (CPU 時間、上下文切換、頁錯誤...)
├── io           # I/O 統計
├── limits       # 資源限制
├── cwd -> /pwd  # 當前工作目錄
├── exe -> /path # 可執行文件
└── root -> /    # 根目錄 (chroot 影響)

七、總結

Linux 進程以 fork() 複製創建、exec() 載入程序、wait() 回收終止,構建以 init 為根的進程樹。線程是共享資源的輕量級進程。掌握 fork/exec/wait 模式、僵屍/孤兒機制、/proc 觀測、ps/pstree/top/htop 分析工具,是 Linux 開發運維的核心基本功。

Linux 進程樹與 fork/exec 流程圖

Copyright © Windows教程網 All Rights Reserved