UNIX 信號和陷阱


信號傳送到一個程式來表示,一個重要的事件已經發生軟體中斷。事件可以從使用者請求存取非法記憶體錯誤。一些信號,例如中斷信號,表明使用者提出的程式來完成的東西,而不是在通常的控制流。

以下是一些你可能會遇到的,要在程式中使用的更常見的信號:

信號名稱 信號數 描述
SIGHUP 1 Hang up detected on controlling terminal or death of controlling process
SIGINT 2 Issued if the user sends an interrupt signal (Ctrl + C).
SIGQUIT 3 Issued if the user sends a quit signal (Ctrl + D).
SIGFPE 8 Issued if an illegal mathematical operation is attempted
SIGKILL 9 If a process gets this signal it must quit immediately and will not perform any clean-up operations
SIGALRM 14 Alarm Clock signal (used for timers)
SIGTERM 15 Software termination signal (sent by kill by default).

信號一覽表:

有一個簡單的方法,列出了所有你的系統支援的信號。只要發出  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

實際的信號列表之間的Solaris,HP-UX 和 Linux

預設操作:

每個信號都有預設與它相關聯的動作。信號的預設操作是,當它接收信號的動作指令碼或程式執行。

有些可能違反的操作是:

  • 終止進程。

  • 忽略信號。

  • 核心轉儲。這將建立一個檔案稱為核心記憶形象的過程,當它收到的信號。

  • 停止進程。

  • 繼續停止的進程。

傳送信號:

有幾種方法提供一個程式或指令碼的信號。其中最常見的是執行指令碼時使用者鍵入Control-C或INTERRUPT 鍵。

當你按下Ctrl+ C鍵傳送一個SIGINT的指令碼,並按照定義的預設動作指令碼終止。

其他常見的傳送信號的方法是使用kill命令的語法如下:

$ kill -signal pid

signal 信號提供的電話號碼或姓名,pid是信號要傳送到的進程ID。範例:

$ kill -1 1001

HUB或掛起信號傳送到正在執行的程式的進程ID 1001。傳送kill信號相同的過程使用以下命令:

$ kill -9 1001

這會殺死正在執行的進程的進程ID 1001。

捕獲信號:

當你按下Ctrl + C鍵或Break鍵在終端一個shell程式的執行過程中,正常程式將立即終止,並返回命令提示字元。這可能並不總是可取的。例如,你可能最終留下了一堆臨時檔案,將不會清理。

捕獲這些信號是很容易的,trap命令的語法如下:

$ trap commands signals

這裡的命令可以是任何有效的Unix命令,或甚至一個使用者定義的函式,信號可以是任意數量的信號,你想來捕獲的列表。

在shell指令碼中的陷阱有三種常見的用途:

  1. 清理臨時檔案

  2. 忽略信號

清理臨時檔案:

trap命令作為一個例子,下面展示了如何可以刪除一些檔案,然後退出,如果有人試圖從終端中止程式:

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

執行shell程式,這個陷阱的角度,這兩個檔案work1$$ 和 dataout$$ 將被自動刪除,如果程式接收信號數為2。 

因此,使用者中斷執行,如果執行的程式後,這個陷阱你可以放心,這兩個檔案將被清理。 exit 命令如下 rm 是必要的,因為沒有它的執行將繼續在節目中的一點,它離開時收到信號。

1號信號產生結束通話:要麼有人故意結束通話線路或線路被意外斷開。

您可以修改前面的陷阱也刪除指定的檔案,在這種情況下,兩個信號信號1號新增到列表:

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

現在,這些檔案將被刪除,如果該行被掛了,或者按Ctrl+ C鍵被按下。

來捕獲指定的命令必須用引號括起來,如果它們包含一個以上的命令。另外請注意,在 shell 命令列掃描 trap 命令得到執行,並再次當一個所列出的的信號被接收的時間。

WORKDIR 值 $$ 所以在前面的例子中,將被取代 trap 命令執行的時間。如果你想這種替代發生在收到信號1或2的時間你可以把單引號內的命令:

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

忽略信號:

如果陷阱列出的命令是空的,指定的信號接收時,將被忽略。例如,下面的命令:

$ trap '' 2

指定的中斷信號是被忽略的。你可能要忽略某些信號時進行一些操作,不希望打斷。可以指定多個信號被忽略如下:

$ trap '' 1 2 3 15

注意,第一個引數必須被指定為一個信號被忽略,而不是相當於寫入下面的內容,它具有獨立的含義也各有:

$ trap  2

如果你忽略了一個信號,所有的子shell也忽略該信號。不過,如果指定要採取的行動在收到的信號,所有的子shell仍然會在收到該信號的預設操作。

重設陷阱:

當你改變了預設在收到信號後應採取的動作,你可以改變它回來的陷阱,如果你只是省略第一個引數;

$ trap 1 2

復位應採取的動作收到信號1或2 返回預設。