首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> 關於C語言

Unix高級編程(APUE)筆記:進程關係與守護進程深度解析

     編輯:關於C語言

APUE 核心概念:終端、會話、進程組與守護進程

《Unix 環境高級編程》(APUE) 第 9 章(進程關係)與第 13 章(守護進程)緊密相關。理解「終端」如何演變為現代終端模擬器,是掌握守護進程脫離控制終端機制的鑰匙。

一、核心層級模型:會話 → 進程組 → 進程 → 線程

  • 終端:早期「笨終端」只負責輸入輸出,計算集中於大型主機。現代終端模擬器(如 Terminal、SSH 客戶端)繼承此概念。
  • 會話:一次成功登錄建立一個會話,是進程組的容器。Shell 登錄即創建會話。
  • 進程組:一組相關進程的集合,分前台/後台。管道命令 ls | more 即創建一個進程組。
  • 關鍵規則:終端只與前台進程組交互;後台進程嘗試讀終端將收到 SIGTTIN 信號被終止。

層級關係:會話包含多個進程組,進程組包含多個進程,進程承載多個線程。內核實際調度單元是線程,PID 本質是線程 ID。

二、關鍵系統調用:setsid() —— 守護進程的基石

#include <unistd.h>
pid_t setsid(void);
  • 調用進程不能是進程組組長(通常先 fork() 讓子進程調用)。
  • 調用後:新會話 + 新進程組 + 脫離控制終端,PID = PGID = SID。
  • 典型模式:父進程 fork() → 子進程 setsid() → 父進程退出 → 子進程成為守護進程。

三、守護進程四大特徵與 ps axj 驗證

特徵表現驗證命令
無控制終端TTY 顯示 ?ps axj 看 TTY 欄
進程組組長PID = PGIDps axj 對比 PID/PGID
會話首進程PID = SIDps axj 對比 PID/SID
父進程為 init(1)PPID = 1ps axj 看 PPID

PID、PGID、SID 三者相等 是守護進程的標誌性特徵。

四、守護進程編程範式(APUE 13.1 圖精簡版)

  1. fork() 並讓父進程退出,子進程成為孤兒進程,被 init 收養。
  2. 子進程調用 setsid() 創建新會話,脫離終端。
  3. chdir("/") 切換工作目錄,防止掛載點無法卸載。
  4. umask(0) 重置文件模式創建掩碼,確保權限可控。
  5. 關閉/重定向標準輸入輸出(通常關閉 0,1,2 或重定向到 /dev/null)。
  6. 可選:處理 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);
  • facility:消息來源(如 LOG_DAEMON 守護進程,LOG_USER 默認)。
  • priority:LOG_EMERG~LOG_DEBUG 八級,以 LOG_ERR 為界區分致命/非致命。
  • openlog 實際是連接 syslogd 服務,非打開文件。
  • 日誌寫入 /var/log/,權限由 syslogd 統一管理,防篡改。

六、單實例守護進程與自啟動

  • 啟動時在 /var/run/ 創建鎖文件(如 pidfile),檢測已存在則報錯退出。
  • 開機自啟動:加入 /etc/rc.d/rc.local 或使用 systemd 服務單元。

七、避坑提醒

  • ❌ 不要盲目忽略 SIGHUP,它是標準的「重讀配置」信號。
  • ❌ 不要關閉所有文件描述符,僅關閉 0/1/2 即可,避免關閉資料庫連接等關鍵 FD。
  • ✅ 使用 daemon(3) 系統調用(BSD/Linux 提供)可簡化上述流程。

理解進程關係模型,是編寫健壯 Unix 系統程序的基石。守護進程本質是「脫離終端、獨立運行的長壽命服務進程」,掌握其創建範式與日誌機制,即可開發生產級後台服務。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved