Linux中的殭屍程序和訊號

2021-08-08 21:38:58 字數 2924 閱讀 1021

通過處理僵死程序來引入訊號的概念;

一、僵死程序:

a.概念:當父程序未結束,子程序結束且父程序未獲取子程序的退出狀態。

b.需要知道的乙個知識點是當程序執行結束,程序主體(執行**、資料、資源)都釋放,但其pcb並未釋放,只是在適當的時機才釋放。

二、怎樣處理僵死程序呢?

想象一下,程序號是有限的,大量的產生僵死程序,將會因為沒有可用的程序號而導致系統不能產生新的程序。因此我們要處理僵死程序:

方法一:父程序呼叫pid_t  wait( int  *status )函式來獲取子程序的退出狀態。

a.函式功能:父程序一旦呼叫了wait就立即阻塞自己,由wait自動分析是否當前程序的某個子程序已經退出,如果讓它找到了乙個已經變成僵死程序的子程序,wait就會收 集這個子程序的資訊,並把它徹底銷毀後返回;如果沒有找到這樣乙個子程序,wait就會一直阻塞在這裡,直到有乙個出現為止。

b.函式返回值:當wait()與fork()配套出現時,如果在使用fork()之前呼叫了wait(),wait()的返回值則為-1,正常情況下返回子程序的pid。

c.引數status用來儲存被收集退出時的一些狀態,它是乙個指向int型別的指標。如果我們對子程序是如何死掉的毫不在意,只想把這個僵死程序消滅掉,我們就可以設定這個引數為null;既pid=wait(null);呼叫成功,就會返回被收集的在子程序的pid,如果呼叫的程序沒有子程序,呼叫失敗,返回-1。

通過以上了解,我們就會想:辛苦建立了乙個子程序,最終子程序和父程序成了序列執行,實際上沒有達到提高效率的目的。

方法二:怎樣非同步處理僵死程序?

我們提出訊號的概念:

(1)、訊號:系統先定義好的某些特定的事件,可以被發生,也可以被接受。發生和接受的主體都是程序。

(2)、系統中訊號的定義:/usr/include/bits/signum.h

a.硬體方式:當使用者在終端上按下某鍵時,將產生訊號;如果按下組合鍵(ctrl+c 代表1)  sigint中斷訊號;ctrl+\代表是3)  sigquit退出訊號;ctrl+z代表19)  sigtstp訊號)後將產生乙個訊號。

硬體異常產生訊號:除資料、無效的儲存訪問等,這些事件通常由硬體(如cpu)檢測到,並將其通知給linux作業系統核心,然後核心生成相應的訊號,並把訊號傳送給該事件發生時正在進行的程式。

b.軟體方式:使用者在終端下呼叫kill命令向程序傳送任務訊號。

(4)、訊號的種類:在shell下輸入kill -l 可顯示linux系統支援的全部訊號;訊號的值定義在signal.h中。每個訊號都由乙個編號和巨集定義名稱。

(5)、訊號的接收:在接受訊號的程序pcb結構中有long signal;通過signal來表示接受到的訊號。

(6)、程序對訊號的響應:當程序發生時,使用者可以要求程序以以下三種方式之一對訊號做出響應:

a.預設訊號:按系統預設方式處理,大部分訊號的預設操作是終止操作,且所有的實時訊號的預設動作都是終止程序。

b.忽略訊號:大多數訊號都可以使用這種方式進行處理,但是sigkill和sigstop這兩個訊號不能被忽略,同時這兩個訊號也不能捕獲和阻塞。此外,如果會忽略某些由硬體異常產生的訊號(如非法儲存訪問或除以0),則程序的行為是不可**的。

c.捕捉訊號:對於捕捉的訊號,可以為其指定訊號處理函式,訊號發生時該函式自動被呼叫,在該函式內部實現對訊號的處理。

(7)、修改訊號的響應方式:修改pcb結構中,struct sigaction結構體陣列中對應訊號值作為下標的函式指標。

函式原型:void  (* signal (int   signum, void    (*fun)  ) (int) ) (int);//signum指定訊號的值;int指函式指標對前面訊號值得處理;

幫助理解:tepedef   void (* fun_handle)(int);

fun_handle   signal( int   signum,fun_handler  fun);

返回值:呼叫成功返回最後一次安裝訊號signum而呼叫signal()時的fun值。失敗則返回sig_err.

(8)、修改訊號的響應方式的時機:程序剛開始就執行修改關注的訊號的響應方式。

**中signal在何時呼叫呢:一般情況main函式開始第一行呼叫。

示例:編寫程式實現使用者第一次輸入ctrl+c時,輸出helloworld;第二次輸入ctrl+c時程式結束:

#include #include #include void fun(int);

int count = 0;

void main()

}void fun(int sign)

(9)、訊號的傳送:int   kill( pid_t  pid, int  signum);//pid表示接受訊號的程序;signum表示訊號型別

標頭檔案:#include

#include

返回值:成功為0;失敗為-1;

舉例:使用者傳入pid向指定程序傳送訊號:

#include #include #include #include #includeint main(int argc, char *argv)

int pid = 0;

sscanf(argv[1], "%d", &pid);

printf("pid == %d\n", pid);

if(kill(pid, sigchld) == -1)

}

(10)、最後結合訊號來處理僵死程序:父程序不阻塞並且處理僵死程序,那子程序結束時,只需向其父程序傳送乙個sigchld訊號。

優勢:a.父程序和子程序可以並行處理;

b.可以處理所有的僵死程序;

#include #include #include #include void fun(int sign)

void main()

else

}

Linux中的殭屍程序

首先,設定sigchld的handler為sig ign能否避免殭屍程序呢?man signal,有以下解釋 避免殭屍程序通常有以下3種方法 1.fork兩次,使得孫子程序的父親為init,孫子程序去執行job init程序只要檢測有子程序終止就會呼叫wait或waitpid釋放資源,防止殭屍程序。...

linux中的。 殭屍 程序

殭屍 程序是乙個早已死亡的程序,但在程序表 processs table 中仍佔了乙個位置 slot 由於程序表的容量是有限的,所以,defunct程序不僅占用系統的記憶體資源,影響系統的效能,而且如果其數目太多,還會導致系統癱瘓,以下是乙個無限建立子程序的程式 i nclude i nclude ...

簡述Linux中的孤兒程序和殭屍程序

父程序先於子程序終止,則子程序變成孤兒程序 乙個臨時中間狀態 系統很快將孤兒程序的父程序設定為init init程序 孤兒領養程序 孤兒收養院 作用 負責作為孤兒程序的父程序,在孤兒程序終止後,程序釋放資源 孤兒程序產生 include include include intmain if pid ...