Linux信號機制與信號處理

信號(signal)是Linux進程間通訊的一種機制,全稱爲軟中斷信號,也被稱爲軟中斷。信號本質上是在軟件層次上對硬件中斷機制的一種模擬。

與其餘進程間通訊方式(例如管道、共享內存等)相比,信號所能傳遞的信息比較粗糙,只是一個整數。但正是因爲傳遞的信息量少,信號也便於管理和使用,能夠用於系統管理相關的任務,例如通知進程終結、停止或者恢復等。

每種信號用一個整型常量宏表示,以SIG開頭,好比SIGCHLD、SIGINT等,它們在系統頭文件<signal.h>中定義。

信號由內核(kernel)管理,產生方式多種多樣:算法

  • 能夠由內核自身產生,好比出現硬件錯誤、內存讀取錯誤,分母爲0的除法等,內核須要通知相應進程。編程

  • 也能夠由其餘進程產生併發送給內核,再由內核傳遞給目標進程。併發


信號傳遞的過程:ide

  • 內核中針對每個進程都有一個表來保存信號。進程

  • 當內核須要將信號傳遞給某個進程時,就在該進程對應的表中寫入信號,這樣就生成了信號。內存

  • 當該進程由用戶態陷入內核態,再次切換到用戶態以前,會查看錶中的信號。若是有信號,進程就會首先執行信號對應的操做,此時叫作執行信號。it

  • 從生成信號到將信號傳遞給對應進程這段時間,信號處於等待狀態。table

  • 咱們能夠編寫代碼,讓進程阻塞(block)某些信號,也就是讓這些信號始終處於等待的狀態,直到進程取消阻塞(unblock)或者忽略信號。class

信號種類

下表列出了一些常見信號:
軟件

信號名稱 數字表示 說明
SIGHUP 1 終端掛起或控制進程終止。當用戶退出Shell時,由該進程啓動的全部進程都會收到這個信號,默認動做爲終止進程。
SIGINT 2 鍵盤中斷。當用戶按下<Ctrl+C>組合鍵時,用戶終端向正在運行中的由該終端啓動的程序發出此信號。默認動做爲終止進程。 
SIGQUIT 3 鍵盤退出鍵被按下。當用戶按下<Ctrl+D>或<Ctrl+\>組合鍵時,用戶終端向正在運行中的由該終端啓動的程序發出此信號。默認動做爲退出程序。
SIGFPE 8 發生致命的運算錯誤時發出。不只包括浮點運算錯誤,還包括溢出及除數爲0等全部的算法錯誤。默認動做爲終止進程併產生core文件。
SIGKILL 9 無條件終止進程。進程接收到該信號會當即終止,不進行清理和暫存工做。該信號不能被忽略、處理和阻塞,它向系統管理員提供了能夠殺死任何進程的方法。
SIGALRM 14 定時器超時,默認動做爲終止進程。
SIGTERM 15 程序結束信號,能夠由 kill 命令產生。與SIGKILL不一樣的是,SIGTERM 信號能夠被阻塞和終止,以便程序在退出前能夠保存工做或清理臨時文件等。


經過 kill -l 命令能夠查看系統支持的全部信號:

$ kill -l
1) SIGHUP       2) SIGINT       3) SIGQUIT      4) SIGILL
5) SIGTRAP      6) SIGABRT      7) SIGBUS       8) SIGFPE
9) SIGKILL     10) SIGUSR1     11) SIGSEGV     12) SIGUSR2
13) SIGPIPE     14) SIGALRM     15) SIGTERM     16) SIGSTKFLT
17) SIGCHLD     18) SIGCONT     19) SIGSTOP     20) SIGTSTP
21) SIGTTIN     22) SIGTTOU     23) SIGURG      24) SIGXCPU
25) SIGXFSZ     26) SIGVTALRM   27) SIGPROF     28) SIGWINCH
29) SIGIO       30) SIGPWR      31) SIGSYS      34) SIGRTMIN
35) SIGRTMIN+1  36) SIGRTMIN+2  37) SIGRTMIN+3  38) SIGRTMIN+4
39) SIGRTMIN+5  40) SIGRTMIN+6  41) SIGRTMIN+7  42) SIGRTMIN+8
43) SIGRTMIN+9  44) SIGRTMIN+10 45) SIGRTMIN+11 46) SIGRTMIN+12
47) SIGRTMIN+13 48) SIGRTMIN+14 49) SIGRTMIN+15 50) SIGRTMAX-14
51) SIGRTMAX-13 52) SIGRTMAX-12 53) SIGRTMAX-11 54) SIGRTMAX-10
55) SIGRTMAX-9  56) SIGRTMAX-8  57) SIGRTMAX-7  58) SIGRTMAX-6
59) SIGRTMAX-5  60) SIGRTMAX-4  61) SIGRTMAX-3  62) SIGRTMAX-2
63) SIGRTMAX-1  64) SIGRTMAX

上面僅是一個演示,不一樣的Linux發行版支持的信號可能不一樣。

每種信號都會有一個默認動做。默認動做就是腳本或程序接收到該信號所作出的默認操做。常見的默認動做有終止進程、退出程序、忽略信號、重啓暫停的進程等,上表中也對部分默認動做進行了說明。

發送信號

有多種方式能夠向程序或腳本發送信號,例如按下<Ctrl+C>組合鍵會發送SIGINT信號,終止當前進程。

還能夠經過 kill 命令發送信號,語法爲:

$ kill -signal pid

signal爲要發送的信號,能夠是信號名稱或數字;pid爲接收信號的進程ID。例如:

$ kill -1 1001

將SIGHUP信號發送給進程ID爲1001的程序,程序會終止執行。

又如,強制殺死ID爲1001的進程:

$ kill -9 1001

捕獲信號

一般狀況下,直接終止進程並非咱們所但願的。例如,按下<Ctrl+C>,進程被當即終止,不會清理建立的臨時文件,帶來系統垃圾,也不會保存正在進行的工做,致使須要重作。

能夠經過編程來捕獲這些信號,當終止信號出現時,能夠先進行清場和保存處理,再退出程序。

用戶程序能夠經過C/C++等代碼捕獲信號,這將在Linux C編程中進行講解,這裏僅介紹若是經過Linux命令捕獲信號。

經過 trap 命令就能夠捕獲信號,語法爲:

$ trap commands signals

commands爲Linux系統命令或用戶自定義命令;signals爲要捕獲的信號,能夠爲信號名稱或數字。

捕獲到信號後,能夠有三種處理:

  • 執行一段腳原本作一些處理工做,例如清理臨時文件;

  • 接受(恢復)信號的默認操做;

  • 忽略當前信號。

1) 清理臨時文件

腳本捕獲到終止信號後一個常見的動做就是清理臨時文件。例如:

$ trap "rm -f $WORKDIR/work1$$ $WORKDIR/dataout$$; exit" 2

當用戶按下<Ctrl+C>後,腳本先清理臨時文件 work1$$ 和 dataout$$ 再退出。

注意:exit 命令是必須的,不然腳本捕獲到信號後會繼續執行而不是退出。

修改上面的腳本,使接收到 SIGHUP 時進行一樣的操做:

$ trap "rm $WORKDIR/work1$$ $WORKDIR/dataout$$; exit" 1 2

幾點注意:

  • 若是執行多個命令,須要將命令用引號包圍;

  • 只有腳本執行到 trap 命令時纔會捕獲信號;

  • 再次接收到信號時還會執行一樣的操做。


上面的腳本,執行到 trap 命令時就會替換 WORKDIR 和 $$ 的值。若是但願接收到 SIGHUP 或 SIGINT 信號時再替換其值,那麼能夠將命令放在單引號內,例如:

$ trap 'rm $WORKDIR/work1$$ $WORKDIR/dataout$$; exit' 1 2

2) 忽略信號

若是 trap 命令的 commands 爲空,將會忽略接收到的信號,即不作任何處理,也不執行默認動做。例如:

$ trap '' 2

也能夠同時忽略多個信號:

$ trap '' 1 2 3 15

注意:必須被引號包圍,不能寫成下面的形式:

$ trap  2

3) 恢復默認動做

若是但願改變信號的默認動做後再次恢復默認動做,那麼省略 trap 命令的 commands 便可,例如:

$ trap 1 2

將恢復SIGHUP 和 SIGINT 信號的默認動做。

相關文章
相關標籤/搜索