什麼是行程(Process)#

行程(Process)是 Linux 對「正在執行的程式」的抽象。當一個可執行檔被載入記憶體並交給 CPU 執行時,kernel 會為它建立一份完整的執行環境,包含位址空間、開啟的檔案、credential 與排程狀態,這份環境就是一個 process。

  • 每個 process 都是獨立的執行單位,擁有自己的虛擬位址空間
  • Process 之間預設是隔離的,需要透過 IPC、signal、共享記憶體等機制溝通
  • Container 內部跑的東西,本質上仍然是 host kernel 看到的 process,只是被 namespace 隔離

重要識別欄位#

每個 process 在 kernel 中都有一組身份識別欄位,這些欄位是後續討論 fork(2)、signal、container 行為的基礎。

  • PID(Process ID):process 的唯一識別碼,由 kernel 在建立時分配
  • PPID(Parent PID):父行程的 PID,記錄誰建立了這個 process
  • UID(User ID)/EUID(Effective UID):擁有者身份,決定權限
  • GID(Group ID):所屬群組
  • PGID(Process Group ID):行程群組,用於 job control 與 signal 廣播
  • SID(Session ID):session 的識別碼,與 terminal 連結
  • TTY:關聯的 terminal device(若有)

Container 內看到的 PID 是 PID namespace 裡的視角,與 host 上的 PID 不同。同一個 process 在 host 看是 PID 12345,在 container 內可能是 PID 1。

Process State#

Linux process 在生命週期中會處於不同狀態,pstop 顯示的狀態欄位即是 kernel 內部追蹤的 task state。

  • R(Running):正在 CPU 上執行,或在 run queue 等待排程
  • S(Interruptible Sleep):等待事件(例如 I/O、signal),可被中斷
  • D(Uninterruptible Sleep):等待硬體 I/O,不可被 signal 中斷,常見於 disk 卡住
  • T(Stopped):被 SIGSTOP 暫停,或被 debugger 控制
  • Z(Zombie):已 exit 但 parent 尚未 wait(2) 收回 exit status
  • X(Dead):即將被釋放,使用者通常看不到

D 狀態的 process 無法用 kill -9 終結。如果一直停在 D,多半是底層 storage 或 NFS 掛點問題。

Process Control Block(PCB)#

Kernel 內部用一個結構體保存 process 所有狀態,這個結構體在 Linux 中稱為 task_struct,概念上對應教科書的 PCB(Process Control Block)。

  • 識別資訊:pid、tgid、real/effective uid/gid
  • 排程資訊:state、priority、scheduling class、CPU affinity
  • 記憶體:mm_struct(位址空間、page table 指標)
  • 檔案:files_struct(fd table)、fs_struct(root、cwd)
  • Signal:signal_struct、sighand_struct(pending signals、handler 表)
  • 親屬關係:parent、children、sibling 連結
  • Namespace:nsproxy(指向各種 namespace 結構)

task_struct 同時用來描述 process 與 thread。Linux 把 thread 視為「共享某些資源的 process」,這也是 clone(2) 系統呼叫的設計基礎。

觀察 Process#

最常用的觀察工具是 pstop/proc 檔案系統。

ps -ef                  # 列出所有 process(BSD 風格)
ps -eLf                 # 連帶顯示 thread
ps -o pid,ppid,uid,stat,cmd
cat /proc/$$/status     # 當前 shell 的 status 檔
ls /proc/1/             # PID 1 的所有 kernel 暴露資訊
  • /proc/<pid>/status:人類可讀的狀態摘要
  • /proc/<pid>/stat:機器可讀的單行狀態(ps 來源)
  • /proc/<pid>/cmdline:完整命令列
  • /proc/<pid>/cgroup:所屬 cgroup(container 判斷依據之一)

為什麼 Container 章節要從 Process 開始#

Container 不是 VM,沒有獨立 kernel。Container 內所有「行程」其實都是 host kernel 排程的 task_struct。理解 PID、PPID、state 與 PCB,才能在後續理解:

  • 為什麼 container 內 PID 1 的 PPID 是 host 上的 shim
  • 為什麼 zombie 與 orphan 在 container 內特別容易出問題
  • 為什麼 signal 會(或不會)穿透 container 邊界

延伸閱讀#

  • man 7 credentials
  • man 5 proc
  • Linux Kernel Source: include/linux/sched.h(task_struct 定義)