信號捕獲trap及其實例應用
1、Linux支持的信號(標紅部分爲常用信號)
信號(Signal):信號是在軟件層次上對中斷機制的一種模擬,通過給一個進程發送信號,執行相應的處理函數。進程可以忽略信號、捕捉信號和執行缺省操作。其中SIGKILL及SIGSTOP兩個信號不能忽略。
1.1、Linux支持的信號列表
編號 | 信號名稱 | 缺省動作 | 描述 |
1 | SIGHUP | 終止 | 終止進程,掛起 |
2 | SIGINT | 終止 | 鍵盤輸入中斷命令,一般是CTRL+C |
3 | SIGQUIT | CoreDump | 鍵盤輸入退出命令,一般是CTRL+\ |
4 | SIGILL | CoreDump | 非法指令 |
5 | SIGTRAP | CoreDump | trap指令發出,一般調試用 |
6 | SIGABRT | CoreDump | abort(3)發出的終止信號 |
7 | SIGBUS | CoreDump | 非法地址 |
8 | SIGFPE | CoreDump | 浮點數異常 |
9 | SIGKILL | 終止 | 立即停止進程,不能捕獲,不能忽略 |
10 | SIGUSR1 | 終止 | 用戶自定義信號1,像Nginx就支持USR1信號,用於重載配置,重新打開日誌 |
11 | SIGSEGV | CoreDump | 無效內存引用 |
12 | SIGUSR2 | 終止 | 用戶自定義信號2 |
13 | SIGPIPE | 終止 | 管道不能訪問 |
14 | SIGALRM | 終止 | 時鐘信號,alrm(2)發出的終止信號 |
15 | SIGTERM | 終止 | 終止信號,進程會先關閉正在運行的任務或打開的文件再終止,有時間進程在有運行的任務而忽略此信號。不能捕捉 |
16 | SIGSTKFLT | 終止 | 處理器棧錯誤 |
17 | SIGCHLD | 可忽略 | 子進程結束時,父進程收到的信號 |
18 | SIGCONT | 可忽略 | 讓終止的進程繼續執行 |
19 | SIGSTOP | 停止 | 停止進程,不能忽略,不能捕獲 |
20 | SIGSTP | 停止 | 停止進程,一般是CTRL+Z |
21 | SIGTTIN | 停止 | 後臺進程從終端讀數據 |
22 | SIGTTOU | 停止 | 後臺進程從終端寫數據 |
23 | SIGURG | 可忽略 | 緊急數組是否到達socket |
24 | SIGXCPU | CoreDump | 超出CPU佔用資源限制 |
25 | SIGXFSZ | CoreDump | 超出文件大小資源限制 |
26 | SIGVTALRM | 終止 | 虛擬時鐘信號,類似於SIGALRM,但計算的是進程佔用的時間 |
27 | SIGPROF | 終止 | 類似與SIGALRM,但計算的是進程佔用CPU的時間 |
28 | SIGWINCH | 可忽略 | 窗口大小改變發出的信號 |
29 | SIGIO | 終止 | 文件描述符準備就緒,可以輸入/輸出操作了 |
30 | SIGPWR | 終止 | 電源失敗 |
31 | SIGSYS | CoreDump | 非法系統調用 |
注意:9 信號,捕獲不住,也無法忽略。
1.2、Linux支持的兩種信號類型
1、標準信號,編號1-31,稱爲非可靠信號(非實時),不支持隊列,信號可能會丟失,比如發送多次相同的信號,進程只能收到一次,如果第一個信號沒有處理完,第二個信號將會丟棄。
2、擴展信號,編號32-64,稱爲可靠信號(實時),支持隊列,發多少次進程就可以收到多少次。
1.3、發送信號的兩種情況
第一種是內核檢測到系統事件,比如鍵盤輸入CTRL+C會發送SIGINT信號。另一種是通過系統調用kill命令來向一個進程發送信號。
2、trap命令語法格式
語法 | 含義 |
trap ' 觸發指令' 信號 | 自定義進程收到系統發出的指定信號後,將執行觸發指令,而不會執行原操作 |
trap '' 信號 | 忽略信號的操作 |
trap '-' 信號 | 恢復原信號的操作 |
trap -p | 列出自定義信號操作 |
信號可以3種表達方法:信號的數字2、全名SIGINT、縮寫INT
3、trap實例應用
例1:打印0-9,ctrl+c不能終止
#!/bin/bash
trap 'echo press ctrl+c' 2
for ((i=0;i<10;i++));do
sleep 1
echo $i
done
分析:i=0,當i<10,每休眠1秒,i+1,捕獲2信號(也就是鍵盤ctrl+c),並把echo後面的內容輸入到終端屏幕。
例2:打印0-5,ctrl+c不能終止,5之後恢復,能終止
#!/bin/bash
trap '' 2
trap -p
for ((i=0;i<5;i++));do
sleep 1
echo $i
done
trap '-' SIGINT
for ((i=5;i<20;i++));do
sleep 1
echo $i
done
分析:i=0,當i<5,每休眠1秒,i+1,捕獲2信號;i>5時,解除捕獲2信號。