Linux 進程非孤立存在,透過進程組、會話、終端機形成層級關係。理解這套機制,才能精準控制背景/前景任務、信號傳遞、Shell 工作控制。
| 概念 | 標識 | 說明 |
|---|---|---|
| 進程 | PID | 執行中程式的實體,init/systemd (PID 1) 為根 |
| 進程組 | PGID | 一組相關進程,領導進程 PID = PGID |
| 會話 | SID | 多個進程組,領導進程 PID = SID,關聯控制終端 |
| 工作 | Job ID (%n) | Shell 管理的進程組,前景/背景 |
$ ps -o pid,pgid,ppid,comm
PID PGID PPID COMMAND
17763 17763 17751 bash # bash 為進程組領導 (PID=PGID)
18534 18534 17763 ps # ps 獨立進程組
18535 18534 17763 cat # cat 屬於 ps 的進程組 (管線)
cmd1 | cmd2 兩命令屬同一進程組 (PGID 相同)kill -SIGTERM -PGID 向整組發送信號setsid() 建立,首進程成會話領導 (SID=PID)stty tostop)# 後台執行 (&)
sleep 100 &
# [1] 12345 ← Job ID %1, PGID 12345
# 查看工作
jobs -l
# [1]+ 12345 Running sleep 100 &
# 前景/背景切換
fg %1 # 背景 → 前景
bg %1 # 暫停 → 背景繼續 (配合 Ctrl+Z)
# 信號發送
kill -TERM %1 # 依 Job ID
kill -TERM -12345 # 依 PGID (負號表進程組)
# 進程組樹狀檢視
ps -ejH
pstree -p
for i in {1..5}; do ./worker $i & done
# 稍後一次發信號全部優雅關閉
kill -TERM 0 # 向當前進程組發送 (含自己)
# 或
pkill -TERM -P $$ # 向所有子進程發送
# 傳統 daemon 化流程
fork() → parent exit() # 1. 脫離父進程
setsid() # 2. 建立新會話,無控制終端
fork() → parent exit() # 3. 確非會話領導,無法重新取得終端
chdir("/") # 4. 釋放掛載點
umask(0) # 5. 重設權限遮罩
close(0,1,2) → open("/dev/null") # 6. 重導標準輸入/輸出/錯誤
systemctl kill -s SIGTERM nginx 精準控制服務進程樹KillMode=control-group|process|mixed 定義停止行為進程組: setpgid(), getpgid(), kill -PGID
會話: setsid(), getsid(), tcsetpgrp() (前景進程組)
工作控制: fg, bg, jobs, kill %n, Ctrl+Z/C/\
現代替代: systemd CGroup, cgroups v2
掌握進程關係模型,從 Shell 操作到系統程式設計,都能精準掌控進程生命週期與信號流向。