《Unix 環境高級編程》(APUE) 第 9 章(進程關係)與第 13 章(守護進程)緊密相關。理解「終端」如何演變為現代終端模擬器,是掌握守護進程脫離控制終端機制的鑰匙。
ls | more 即創建一個進程組。SIGTTIN 信號被終止。層級關係:會話包含多個進程組,進程組包含多個進程,進程承載多個線程。內核實際調度單元是線程,PID 本質是線程 ID。
setsid() —— 守護進程的基石#include <unistd.h>
pid_t setsid(void);
fork() 讓子進程調用)。fork() → 子進程 setsid() → 父進程退出 → 子進程成為守護進程。ps axj 驗證| 特徵 | 表現 | 驗證命令 |
|---|---|---|
| 無控制終端 | TTY 顯示 ? | ps axj 看 TTY 欄 |
| 進程組組長 | PID = PGID | ps axj 對比 PID/PGID |
| 會話首進程 | PID = SID | ps axj 對比 PID/SID |
| 父進程為 init(1) | PPID = 1 | ps axj 看 PPID |
PID、PGID、SID 三者相等 是守護進程的標誌性特徵。
fork() 並讓父進程退出,子進程成為孤兒進程,被 init 收養。setsid() 創建新會話,脫離終端。chdir("/") 切換工作目錄,防止掛載點無法卸載。umask(0) 重置文件模式創建掩碼,確保權限可控。/dev/null)。SIGHUP 實現配置熱加載(非必須忽略)。守護進程無終端,不能用 printf。需使用 syslog 機制:
#include <syslog.h>
void openlog(const char *ident, int option, int facility);
void syslog(int priority, const char *format, ...);
void closelog(void);
LOG_DAEMON 守護進程,LOG_USER 默認)。LOG_EMERG~LOG_DEBUG 八級,以 LOG_ERR 為界區分致命/非致命。openlog 實際是連接 syslogd 服務,非打開文件。/var/log/,權限由 syslogd 統一管理,防篡改。/var/run/ 創建鎖文件(如 pidfile),檢測已存在則報錯退出。/etc/rc.d/rc.local 或使用 systemd 服務單元。SIGHUP,它是標準的「重讀配置」信號。daemon(3) 系統調用(BSD/Linux 提供)可簡化上述流程。理解進程關係模型,是編寫健壯 Unix 系統程序的基石。守護進程本質是「脫離終端、獨立運行的長壽命服務進程」,掌握其創建範式與日誌機制,即可開發生產級後台服務。