linux下的訊號機制(signel)--持續更新中
1、訊號的基本概念
程序之間可以互相通過系統呼叫kill傳送軟中斷訊號。核心也可以因為內部事件而給程序傳送訊號,通知程序發生了某個事件。程序通過系統呼叫signal來指定程序對某個訊號的處理行為。
2、訊號本質是int型數字編號(事先定義好的)
解釋:訊號只是用來通知某程序發生了什麼事件,並不給該程序傳遞任何資料(比如文字,語音等資料),他是核心事先定義好的int數字,呼叫signal函式時,來指定訊號內型。
3、誰發出的訊號
(1)使用者在ubuntu終端(終端就是一個前臺執行的程序)按下按鍵比如ctrl+C等
(2)硬體異常後,作業系統核心傳送訊號
(3)使用者使用kill命令(是一個核心提供的API函式)比如用:kill - 9 xxx
(4)某種軟體條件滿足後也會發送訊號,如alarm鬧鐘時間到會產生SIGALARM訊號、向一個讀端已近關閉的管道write時,會產生SIGPIPE
4、訊號由誰處理,處理方式
(1)捕獲訊號,程序可以指定處理函式,由該函式來處理。
(2)忽略訊號,對該訊號不做任何處理,就象未發生過一樣。
(3)預設處理,這種預設操作,對大部分的訊號的預設操作是使得程序終止。
5、每個int型的訊號值發生的原因(這裡列出常見的幾種)
5.1在linux下/usr/include/i386-linux-gnu/bits 下的signum.h定義了所以的訊號值
訊號 值 處理動作 發出訊號的原因
SIGHUP 1 A 終端掛起或者控制程序終止
SIGINT 2 A 鍵盤中斷(如break鍵被按下) 正常終止
SIGQUIT 3 C 鍵盤的退出鍵被按下
SIGILL 4 C 非法指令
SIGABRT 6 C 由abort(3)發出的退出指令,異常終止
SIGIO 23,29,22 A 某I/O操作現在可以進行了(4.2 BSD)
SIGKILL 9 AEF 殺死程序的終極方法
SIGSEGV 11 C 無效的記憶體引用
SIGPIPE 13 A 管道破裂: 寫一個沒有讀埠的管道
SIGALRM 14 A 由alarm(2)發出的訊號
SIGTERM 15 A 終止訊號
SIGUSR1 30,10,16 A 使用者自定義訊號1 給使用者做程序間通訊,不像其他的處理方法被綁定了
SIGUSR2 31,12,17 A 使用者自定義訊號2
SIGCHLD 20,17,18 B 子程序結束訊號
SIGCONT 19,18,25 程序繼續(曾被停止的程序)
SIGSTOP 17,19,23 DEF 終止程序
SIGTSTP 18,20,24 D 控制終端(tty)上按下停止鍵
SIGTTIN 21,21,26 D 後臺程序企圖從控制終端讀
SIGTTOU 22,22,27 D 後臺程序企圖從控制終端寫
5.2處理動作一項中的字母含義如下
A 預設的動作是終止程序B 預設的動作是忽略此訊號
C 預設的動作是終止程序並進行核心映像轉儲(dump core)
D 預設的動作是停止程序
E 訊號不能被捕獲
F 訊號不能被忽略
6、程序對訊號的處理例項
6.1、signal系統呼叫
(1)宣告如下: typedef void (*sighandler_t) (int);sighandler_t signal( int signum, sighandler_t handler ); 解釋:sighandler_t是一個函式指標,這個函式指標指向的函式接受一個int引數,返回一個void 型別 (2)在呼叫中,引數signum指出要設定處理方法的訊號。第二個引數handler是一個處理函式,或者是 SIG_INT:捕獲這個訊號,並處理handler函式
SIG_IGN:忽略引數signum所指的訊號。
SIG_DFL:恢復引數signum所指訊號的處理方法為預設值。
(3)細節:
一、signal函式繫結一個捕獲函式後訊號發生後會自動執行繫結的捕獲函式,並且把訊號編號作為傳參傳給捕獲函式
二、signal的返回值在出錯時為SIG_ERR,繫結成功時返回舊的捕獲函式
6.2、signal程式碼示例
#include <stdio.h>
#include <signal.h>
#include <stdlib.h>
typedef void (*sighandler_t)(int); //下面使用核心用sighandler_t定義的SIG_DFL,需要宣告一下
void func(int sig)
{
if (SIGINT != sig)
return 0;
printf("func for signal: %d.\n", sig);
}
int main(void)
{
sighandler_t ret = (sighandler_t)(-2); //
//signal(SIGINT, func) ;
//signal(SIGINT, SIG_DFL);// 指定訊號SIGINT為預設處理
ret = signal(SIGINT, SIG_IGN); // 指定訊號SIGINT為忽略處理
if (SIG_ERR == ret)
{
perror("signal:");
exit(-1);
}
printf("before while(1)\n");
while(1);
printf("after while(1)\n");
return 0;
}