1. 父進程正確回收子進程資源
父進程是回收子進程資源的主體,需通過系統調用主動等待子進程結束。常用函數包括wait()
(阻塞父進程直至指定子進程終止)和waitpid()
(支持非阻塞模式,可等待任意子進程)。例如,父進程調用waitpid(pid, &status, 0)
會阻塞直到子進程pid
結束,并回收其資源,徹底避免僵尸進程產生。
2. 捕獲SIGCHLD信號處理子進程退出
子進程結束時,內核會向父進程發送SIGCHLD
信號。父進程可通過設置信號處理函數,在信號觸發時調用waitpid()
回收資源。示例代碼:定義sigchld_handler
函數,在其中循環調用waitpid(-1, NULL, WNOHANG)
(非阻塞方式回收所有終止的子進程);通過sigaction
函數注冊該處理函數(設置sa_flags = SA_RESTART
避免信號中斷系統調用)。這種方法能實時響應子進程退出,及時回收資源。
3. 使用nohup命令忽略掛起信號
當終端關閉時,終端會向關聯進程發送SIGHUP
信號,默認會導致進程終止。使用nohup your_command &
運行程序,可使進程忽略SIGHUP
信號,并將輸出重定向到nohup.out
文件。此時,即使終端關閉,進程仍由init
進程(PID=1)接管,由其負責回收子進程資源,避免僵尸進程產生。
4. 子進程中調用setsid()創建新會話
子進程調用setsid()
函數可創建新會話,脫離原父進程的控制終端和進程組,成為新會話的首進程。此時,子進程不再受原父進程退出的影響,其資源將由init
進程回收。示例:父進程fork()
后,子進程調用setsid()
,隨后執行后續任務。這種方法適用于需要長期運行的后臺進程。
5. 將程序轉換為守護進程
守護進程是運行在后臺、脫離終端控制的特殊進程,通常由init
或systemd
管理,能自動回收子進程資源??赏ㄟ^daemon()
函數(如daemon(0, 0)
)將程序轉換為守護進程,該函數會完成fork()
、setsid()
、關閉標準文件描述符等操作。此外,使用systemd
創建服務(編寫.service
文件,配置ExecStart
、Restart
等參數),由systemd
管理進程生命周期,也是現代Ubuntu系統中常用的守護進程管理方式。
6. 使用systemd管理服務
systemd
是Ubuntu的默認初始化系統,能自動管理進程的啟動、停止和重啟,并回收僵尸進程。通過創建.service
文件(位于/etc/systemd/system/
),配置[Service]
部分的ExecStart
(指定程序路徑)、Restart
(設為on-failure
或always
,進程異常退出時自動重啟)等參數;運行sudo systemctl daemon-reload
加載配置,sudo systemctl start service_name
啟動服務,sudo systemctl enable service_name
設置開機自啟。systemd
會監控服務進程,及時回收其子進程資源。