Linux基礎篇 訊號

2021-07-14 15:17:02 字數 4857 閱讀 8590

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...