在 Linux 中向殭屍程序發送 SIGKILL 時會發生什麼?
在Linux中,當一個子程序終止並且它的父程序還沒有等待它時,它就變成了一個殭屍程序。孩子的退出程式碼儲存在 pid 描述符中。
如果將 a
SIGKILL
發送給孩子,則不應有任何影響。這是否意味著退出程式碼不會被 修改,
SIGKILL
或者退出程式碼會被修改以指示子退出,因為它收到了一個SIGKILL
?
要回答這個問題,您必須了解信號如何發送到程序以及程序如何存在於核心中。
每個程序都表示為
task_struct
核心內部的一個(定義在sched.h
標頭檔中並從這裡開始)。該結構包含有關該過程的資訊;例如pid。重要資訊在儲存相關信號的第 1566 行中。僅當向程序發送信號時才設置此項。死程序或殭屍程序仍然有一個
task_struct
. 結構保持不變,直到父程序(自然或通過收養)wait()
在接收後呼叫SIGCHLD
以獲取其子程序。發送信號時,signal_struct
設置 。在這種情況下,信號是否可擷取並不重要。**每次程序執行時都會評估信號。**或者準確地說,在程序執行*之前。*該過程隨後處於該
TASK_RUNNING
狀態。核心執行schedule()
常式,根據其調度算法確定下一個執行程序。假設該程序是下一個正在執行的程序,signal_struct
則評估 的值,判斷是否有等待信號要處理。如果手動定義了信號處理程序(通過signal()
或sigaction()
),則執行註冊的函式,否則執行信號的預設操作。預設操作取決於發送的信號。例如,
SIGSTOP
信號的預設處理程序會將目前程序的狀態更改為TASK_STOPPED
然後執行schedule()
以選擇要執行的新程序。請注意,SIGSTOP
不可擷取(如SIGKILL
),因此無法註冊手動信號處理程序。如果出現無法擷取的信號,將始終執行預設操作。對於你的問題:
調度程序永遠不會確定已失效或死的程序
TASK_RUNNING
再次處於該狀態。因此核心永遠不會為相應的信號執行信號處理程序(預設或定義),無論是哪個信號。因此,exit_signal
將永遠不會再次設置。signal_struct
通過設置程序的in將信號“傳遞”到task_struct
程序,但不會發生其他任何事情,因為該程序將永遠不會再次執行。沒有要執行的程式碼,該程序剩下的就是該程序結構。但是,如果父程序通過 獲得其子程序
wait()
,則它收到的退出程式碼是該程序“最初”死亡時的退出程式碼。是否有信號等待處理並不重要。