linux下的訊號列表
列表中,編號為1 ~ 31的訊號為傳統unix支援的訊號,是不可靠訊號(非實時的),編號為32 ~ 63的訊號是後來擴充的,稱做可靠訊號(實時訊號)。不可靠訊號和可靠訊號的區別在於前者不支援排隊,可能會造成訊號丟失,而後者不會。
訊號的產生方式有四種:
1、硬體中斷
2、命令列(指令)
3、函式呼叫
4、軟體條件(程式異常)
訊號的處理動作有三種:
1、忽略此訊號
2、執行該訊號的預設處理動作(一般為結束該程序)
3、執行乙個訊號處理函式,要求核心在處理此訊號時切換到使用者態執行(稱為捕捉乙個訊號)
自定義訊號處理函式
**如下:
#include
#include
#include
void fun()
int main()
return
0;}
1、通過終端按鍵產生訊號
core檔案
在sigint的預設處理動作是要終止程序,sigquit的預設動作是終止程序並core dump,當⼀乙個程序要異常終⽌止時,可以選擇把程序的⽤使用者空間記憶體資料全部 儲存到磁碟上,⽂檔名通常是core,這叫做core dump。程序異常終⽌止通常是因為有bug,⽐比如⾮非法記憶體訪問導致段錯誤,事後可以⽤用偵錯程式檢查core⽂檔案以查清錯誤原因,這叫做post-mortem debug(事後除錯)。⼀乙個程序允許產⽣生多⼤大的core⽂檔案取決於程序的resource limit(這個資訊儲存 在pcb中)。預設是不允許產⽣生core⽂檔案的,因為core⽂檔案中可能包含⽤使用者密碼等敏感資訊,不安全。在開發除錯階段可以⽤用ulimit命令變這個限制,允許產⽣生core⽂檔案。
core檔案大小預設是0,所以不設定的話不會生成core檔案
core檔案最大可以為1024kb,我們通過ulimit -c 1024命令設定core檔案大小
在死迴圈程式中我們按下ctrl+』c』或ctrl+』\』,終止該程序,此時生成core檔案,
2、通過系統函式向程序發訊號
(1) kill命令是呼叫kill函式實現的,kill函式可以給乙個指定的程序發特定的訊號。
kill -訊號標誌 程序標號
函式原型
#include
int kill(pid_t pid,int signo);
int raise(int signo);
raise函式可以給當前程序傳送指定的訊號
(2) abort函式使當前程序接收到訊號異常終止
函式原型 void abort(void);//和exit 函式一樣,abort函式總是會成功的,所以沒有返回值
3、由軟體條件產生訊號
#include
unsigned in alarm(insigned int seconds);
函式原型如上,呼叫alarm函式可以設定乙個鬧鐘,也就是告訴核心在seconds秒後向程序傳送乙個sigalrm訊號
1
#include
2#include
3#include45
int main()
6 13return
0; 14 }
執行結果為1s中計算機計數次數
阻塞訊號以及相關函式
幾個概念:
實際執行訊號的處理動作稱為訊號遞達(delivery)。
訊號從產生到遞達之間的狀態,稱為訊號未決(pending)。
程序可以選擇阻塞(block )某個訊號。被阻塞的訊號產⽣生時將保持在未決狀態,直到程序解除對此訊號的阻塞,才 執行遞達的動作。
,阻塞和忽略是不同的,只要訊號被阻塞就不會遞達,而忽略是在遞達之後 可選的一種處理動作。
訊號在核心中的表示示意圖
每個訊號都有兩個標誌位分別表⽰示阻塞(block)和未決(pending),還有⼀乙個函式指標表⽰示處理
動作。訊號產⽣生時,核心在程序控制塊中設定該訊號的未決標誌,直到訊號遞達才清除該標
志。在上圖的例⼦子中,
1. sighup訊號未阻塞也未產生過,當它遞達時執⾏行預設處理動作。
2. sigint訊號產生過,但正在被阻塞,所以暫時不能遞達。雖然它的處理動作是忽略,但在沒 有解除阻塞之前不能忽略這個訊號,因為程序仍有機會改變處理動作之後再解除阻塞。
3. sigquit訊號未產生過,⼀一旦產生sigquit訊號將被阻塞,它的處理動作是使用者自定義函式sighandler。
訊號集操作函式
sigset_t型別對於每種訊號用乙個bit表⽰示「有效」或「無效」狀態,至於這個型別內部如何儲存這 些bit則依賴於系統實現,從使用者的角度是不必關心的,使用者只能呼叫以下函式來操 作sigset_t變數。
幾個函式原型:
#include
int sigemptyset(sigset_t *set);
int sigfillset(sigset_t * set);
int sigaddset(sigset_t *set ,int signo);
int sigdelset(sigset_t *set,int signo);
int sigismenber(cosnt sigset_t *set,int signo);
函式sigemptyset初始化set所指向的訊號集,使其中所有訊號的對應bit清零,表示該訊號集不包含 任何有效訊號。函式sigfillset初始化set所指向的訊號集,使其中所有訊號的對應bit置位,表示 該訊號集的有效訊號包括系統支援的所有訊號。注意,在使用sigset_t型別的變數之前,一定要調 ⽤用sigemptyset或sigfillset做初始化,使訊號集處於確定的狀態。初始化sigset_t變數之後就可以 在呼叫sigaddset和sigdelset在該訊號集中新增或刪除某種有效訊號。這四個函式都是成功返回0,出錯返回-1。sigismember是乙個布林函式,用於判斷乙個訊號集的有效訊號中是否包含某種 訊號,若包含則返回1,不包含則返回0,出錯返回-1。
sigprocmask
int sigprocmask(int how,const sigset_t *set,sigset_t *oset)
呼叫函式sigprocmask可以讀取或更改程序的訊號遮蔽字(阻塞訊號集)。
返回值:若成功則為0,若出錯則為-1
如果oset是非空指標,則讀取程序的當前訊號遮蔽字通過oset引數傳出。如果set是非空指標,則 更改程序的訊號遮蔽字,引數how指⽰示如何更改。如果oset和set都是非空指標,則先將原來的訊號 遮蔽字備份到oset裡,然後根據set和how引數更改訊號遮蔽字。假設當前的訊號遮蔽字為mask,下表說明了how引數的可選值。
如果呼叫sigprocmask解除了對當前若干個未決訊號的阻塞,則sigprocmask返回前,⾄至少將其中 乙個訊號遞達。
sigpending
int sigpending(sigset_t *set)
sigpending**讀取當前程序的未決訊號集**,通過set引數傳出。呼叫成功則返回0,出錯則返回-1。
下面通過程式來演示函式的功能
#include
#include
#include
void printsigset(sigset_t *set)
else
}printf("\n");
}int main()
return
0;}
執行結果如下:
我們可以發現,在沒有按下ctrl+『c』時,當前程序中未決訊號集一直為0,在按下後,第二位變成了1。因為在按下ctrl+』c』時訊號被阻塞,一直處於未決狀態。
我們將**修改如下:
修改while迴圈
while(1)
count++;
sleep(1);
}
執行結果如下:
當ctrl+『c』按下且if語句執行後,程序退出,因為此時訊號已經為未決狀態且未阻塞,所以執行預設動作,終止程序。
signal訊號處理基礎篇
signal函式的原型如下void signal int void fun int int 由此可見該函式的返回值是乙個指向 void fun int 型別的指標,即返回上一次和該訊號繫結的 訊號處理函式位址。程序對訊號的處理有三種方式 1 忽略此訊號,如signal sigint,sig ign ...
linux基礎 訊號阻塞及未決訊號
未決訊號 pause的使用 訊號傳送處理過程 可重入函式 訊號處理函式的繼承 setitimer實現定時器 程序可以設定對某個訊號的阻塞 遮蔽 需要用到sigset t 訊號集 資料型別。sigemptyset 3 include int sigemptyset sigset t set 功能 將訊...
程序篇 訊號
訊號 signal 改變訊號的響應方式 signal 引數1,引數2 看一下 sig dfl 預設 sig ign 忽略 fun 自定義 kill 傳送訊號 int kill pid t pid,int sig kill pid,訊號名 乙個程序呼叫kill函式可以傳送訊號到另乙個程序.可以用kil...