Linux

在 Linux 中向殭屍程序發送 SIGKILL 時會發生什麼?

  • January 6, 2020

在Linux中,當一個子程序終止並且它的父程序還沒有等待它時,它就變成了一個殭屍程序。孩子的退出程式碼儲存在 pid 描述符中。

如果將 aSIGKILL發送給孩子,則不應有任何影響。

這是否意味著退出程式碼不會被 修改,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(),則它收到的退出程式碼是該程序“最初”死亡時的退出程式碼。是否有信號等待處理並不重要。

引用自:https://unix.stackexchange.com/questions/256926