程序篇 訊號

2021-09-26 08:49:58 字數 3047 閱讀 1581

訊號是什麼?

訊號其實就是傳遞的一種資訊,讓我們能根據這個資訊進一步的去處理響應的事件。比如說:紅綠燈,綠燈亮了,這就是乙個訊號,提醒我們此時可以安全的過馬路了。比如我們鍵盤按下:ctrl-c 給前台程序傳送訊號,終止程序。

對於訊號的理解,我們可以模擬現實生活,舉個例子:老師給我們布置了乙個作業,然後我們將作業記錄下來是什麼,然後需要一段時間去完成作業,最後上交給老師。linux下訊號同樣如此,需要產生乙個訊號,然後在乙個適合的時間,程序去進行處理。

訊號實質是軟中斷,用於通知程序發生某些事件。

訊號作用:通知事件的發生,訊號產生之後第一時間也不是直接處理,而是先儲存下來。再處理訊號

訊號生命週期:訊號的產生—>訊號的註冊—>訊號的堵塞—>訊號的登出—>訊號的處理

訊號是系統預先定義好的某些特定的事件,訊號可以被產生,可以被接收,產生和接收的主體都是程序。程序收到訊號之後,會有三種響應方式:忽略、預設、自定義(捕獲)

1.忽略此訊號。

2.執行該訊號的預設處理動作(終止該訊號)

3.提供乙個訊號處理函式(自定義動作),要求核心在處理該訊號時切換到使用者態執行這個處理函式,這種方式被稱為 捕捉(catch)乙個訊號。

產生訊號的方式

(1)通過終端按鍵(組合鍵)產生訊號

使用者在終端按下某些鍵時,終端驅動程式會傳送訊號給前台程序,例如ctrl-c 產生sigint訊號,ctrl-\ 產生sigouit訊號等

概念:當乙個程序要異常終止時,可以選擇把程序的使用者空間記憶體資料全部儲存到磁碟上,檔名通常是core,這叫做core dump,也叫 核心轉儲,幫助開發者進行除錯,在程式崩潰時把記憶體資料dump到磁碟上,讓gdb 識別。

(2)硬體異常產生的訊號

硬體異常產生訊號,這些條件由硬體檢測到並通知核心,然後核心向當前程序傳送適當的訊號。 例如當前程序執行了除以0的指令,cpu的運算單元會產生異常,核心將這個異常解釋為 sigfpe訊號傳送給程序。 再比如當前程序訪問了非法記憶體位址,mmu會產生異常,核心將這個異常解釋為sigse** 訊號傳送給程序。

(3)呼叫系統函式向程序發訊號

1. 乙個程序可以呼叫 kill(2)函式 傳送訊號給另乙個程序。可以用kill(1)命令傳送訊號給某個程序,kill(1)命令也是呼叫kill(2)函式實現的,如果不明確指定訊號則傳送給 sigtrem訊號,該訊號的預設處理動作是終止程序。

2.raise函式可以給當前程序傳送訊號,相當於自己給自己發訊號。

#includeint kill(pid_t pid, int signal);

int raise(int signal);

//都是成功返回0,失敗返回-1;

3. absort函式可以使當前程序接收到訊號而異常終止

#includevoid absort(void);

//沒有返回值,總能呼叫成功;

(4)由軟體條件產生訊號

1.sigpipe 是一種軟體條件產生的訊號。在匿名管道中,如果讀端的檔案描述符關閉了,那麼寫端就會傳送sigpipe來 導致write程序終止退出。

2.alarm函式可以設定乙個鬧鐘,在seconds 之後給當前程序傳送乙個sigalarm訊號,該訊號的預設處理時結束當前程序。

#includeunsigned int alarm(unsigned int seconds);

//返回值是0或者返回值是當前second餘下的秒數;

//函式的返回值仍是以前鬧鐘設定的餘下秒數

signal()函式可以修改訊號的響應方式:

typedef  void (*sighandle_t)(int);

sighandle_t (*signal,sighandle_t);

忽略:  sig_ign

預設:  sig_dfl

自定義:  自己寫的訊號處理函式

kill函式可以向指定的程序傳送指定的訊號:

int  kill(pid_t  pid ,  int  signo);

pid > 0   指定將訊號傳送給那個程序

pid==0   訊號被傳送到和當前程序在同乙個程序組的程序

pid == -1  將訊號傳送給系統上有許可權傳送的所有的程序

pid < -1   將訊號傳送給程序組id等於pid 絕對值,並且有許可權傳送的所有的程序。

sig      指定傳送訊號的型別

raise函式將訊號傳送給自己:

int  raise(int sig);

相當於:  kill(getpid,sig);

訊號集在實際的應用中乙個應用層程式需要對多個訊號進行處理,為了方便,linux系統引進了訊號集概念。訊號集用多個訊號組成的資料型別sigset_t。可用以下的系統呼叫設定訊號集中國所包含的資料。

int  sigemptyset(sigset_t  *set);  將set集合置空,成功則返回0,失敗則返回-1.

int  sigaddset(sigset_t *set, int signo)將signal訊號加入到 set集合,成功則返回0,失敗則返回-1.

int  sigdelset(sigset_t*set,int signo);  從set集合中移除signo訊號,成功則返回0,失敗則返回-1.

int  sigismember(const sigset_t  *set , int signo );  signo 判斷訊號是否存在於set集合中,若真返回1,假返回0,失敗返回-1.

int sigprocmask(int how, const  sigset_t  *set,sigset_t *oset);  用於檢測或更改其訊號遮蔽字,包含標頭檔案,成功則返回0,失敗則返回1.

引數:how 指示如何修改遮蔽訊號

set 是乙個非空指標時,根據how修改遮蔽訊號。

oset是乙個 非空指標時,存放當前遮蔽訊號集

若set為null ,不改變該程序的訊號遮蔽字,how也意義。

程序篇 訊號

訊號 signal 改變訊號的響應方式 signal 引數1,引數2 看一下 sig dfl 預設 sig ign 忽略 fun 自定義 kill 傳送訊號 int kill pid t pid,int sig kill pid,訊號名 乙個程序呼叫kill函式可以傳送訊號到另乙個程序.可以用kil...

Linux程序訊號 訊號處理

一 訊號相關概念 1.實際執行訊號的處理動作稱為訊號遞達 delivery 2.訊號從產生到遞達之間的狀態稱為訊號未決 pending 不一定會立即delivery 3.程序可以選擇阻塞 block 某個訊號。不會遞達 4.被阻塞的訊號產生時將保持在未決狀態,知道程序解除對此訊號 的阻塞,才會執行遞...

程序通訊 訊號

訊號是程序間通訊機制中唯一的非同步通訊機制。訊號的分類 根據可靠性 可靠訊號 不可靠訊號 根據與時間的關係 實時訊號 非實時訊號 程序可以通過下面三種方式來處理乙個訊號 1.忽略訊號 大多數訊號都按照這種方式進行處理,但有兩種訊號決不能被忽略,它們是 sigkill sigstop。這兩種訊號不能被...