僵尸進程(Zombie Process)是指在操作系統中,一個進程已經終止執行了(即已經退出),但是其父進程還沒有通過 wait()
系統調用來獲取該進程的終止狀態(exit status),因此該進程的進程描述符仍然存在,操作系統會將其保留在進程表中,但此時它已經不能執行任何操作,也不再占用系統資源。
通常情況下,一個進程在結束后會通過向其父進程發送信號或者父進程通過主動調用 wait()
或 waitpid()
來回收其資源。如果父進程沒有回收其子進程的資源,那么子進程的進程描述符就會保留在系統中,形成僵尸進程。
僵尸進程本身不會消耗系統資源(如CPU時間或內存),但如果大量的僵尸進程積累,會導致進程表變滿,使得系統無法創建新的進程,從而影響系統的正常運行。
為了避免僵尸進程的產生,父進程在創建子進程后,應該及時回收子進程的資源,可以通過捕獲 SIGCHLD
信號并調用 wait()
或 waitpid()
來處理。
-
產生原因:僵尸進程通常由于父進程沒有及時回收子進程資源而產生。這可能是因為父進程在處理多個子進程時,沒有正確調用
wait()
或waitpid()
來獲取子進程的終止狀態。 -
檢測和診斷:可以通過命令行工具(如
ps aux | grep Z
)或編程接口(如在程序中使用waitpid()
函數)來檢測系統中是否存在僵尸進程,進而進行診斷和處理。 -
影響和風險:雖然僵尸進程本身不會消耗大量資源,但是大量的僵尸進程會占用系統資源表項,導致系統性能下降甚至系統無法正常運行。
-
處理方法:正確的處理方法是確保父進程在子進程結束后,及時調用
wait()
或waitpid()
函數來回收子進程的資源。另外,也可以通過設置信號處理器來捕獲SIGCHLD
信號,在信號處理函數中處理僵尸進程。
在Linux系統中,當一個父進程退出時,其子進程會被init
進程接管。init
進程在Linux系統中通常由systemd
或者SysV init
等進程管理器扮演,而且會自動接管已成為孤兒的子進程。接管的意思是它們成為新的父進程,并可以等待他們的狀態消息。
如果子進程在 init
進程接管之前已經成為僵尸進程,那么 init
進程會接管并處理這些僵尸進程。具體來說,當父進程退出時,如果它的子進程已經結束但父進程尚未調用 wait()
或 waitpid()
獲取子進程的退出狀態,那么子進程就會變成僵尸進程。此時,操作系統會將這些僵尸進程的父進程設置為 init
進程(PID 1)。init
進程會周期性地調用 wait()
或 waitpid()
來清理僵尸進程,這是因為 init
進程作為所有其他進程的祖先進程,負責回收所有孤兒進程的資源。
因此,即使子進程在被 init
進程接管之前已經成為僵尸進程,init
進程也會負責最終清理這些僵尸進程,釋放它們占用的系統資源。