什麼是行程(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 在生命週期中會處於不同狀態,ps 與 top 顯示的狀態欄位即是 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#
最常用的觀察工具是 ps、top 與 /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 定義)