對於 linux來說,實際訊號是軟中斷,許多重要的程式都需要處理訊號。訊號,為 linux 提供了一種處理非同步事件的方法。比如,終端使用者輸入了 ctrl+c 來中斷程式,會通過訊號機制停止乙個程式。
1、訊號的名字和編號:
每個訊號都有乙個名字和編號,這些名字都以「sig」開頭,例如「sigio 」、「sigchld」等等。
訊號定義在signal.h標頭檔案中,訊號名都定義為正整數。
具體的訊號名稱可以使用kill -l來檢視訊號的名字以及序號,訊號是從1開始編號的,不存在0號訊號。kill對於訊號0又特殊的應用。
訊號的名稱
訊號的處理:
訊號的處理有三種方法,分別是:忽略、捕捉和預設動作
捕捉訊號,需要告訴核心,使用者希望如何處理某一種訊號,說白了就是寫乙個訊號處理函式,然後將這個函式告訴核心。當該訊號產生時,由核心來呼叫使用者自定義的函式,以此來實現某種訊號的處理。
系統預設動作,對於每個訊號來說,系統都對應由預設的處理動作,當發生了該訊號,系統會自動執行。不過,對系統來說,大部分的處理方式都比較粗暴,就是直接殺死該程序。
具體的訊號預設動作可以使用man 7 signal來檢視系統的具體定義。在此,我就不詳細展開了,需要檢視的,可以自行檢視。也可以參考 《unix 環境高階程式設計(第三部)》的 p251——p256中間對於每個訊號有詳細的說明。
了解了訊號的概述,那麼,訊號是如何來使用呢?
其實對於常用的 kill 命令就是乙個傳送訊號的工具,kill 9 pid來殺死程序。比如,我在後台執行了乙個 top 工具,通過 ps 命令可以檢視他的 pid,通過 kill 9 來傳送了乙個終止程序的訊號來結束了 top 程序。如果檢視訊號編號和名稱,可以發現9對應的是 9) sigkill,正是殺死該程序的訊號。而以下的執行過程實際也就是執行了9號訊號的預設動作——殺死程序。
kill 殺死程序
1、入門版:signal
2、高階版:sigaction
訊號傳送函式也不止乙個,同樣分為入門版和高階版
1.入門版:kill
2.高階版:sigqueue
在正式開始了解這兩個函式之前,可以先來思考一下,處理中斷都需要處理什麼問題。
按照我們之前思路來看,可以傳送的訊號型別是多種多樣的,每種訊號的處理可能不一定相同,那麼,我們肯定需要知道到底發生了什麼訊號。
另外,雖然我們知道了系統發出來的是哪種訊號,但是還有一點也很重要,就是系統產生了乙個訊號,是由誰來響應?
如果系統通過 ctrl+c 產生了乙個 sigint(中斷訊號),顯然不是所有程式同時結束,那麼,訊號一定需要有乙個接收者。對於處理訊號的程式來說,接收者就是自己。
開始的時候,先來看看入門版本的訊號註冊函式,他的函式原型如下:
signal 的函式原型
在 這個標頭檔案中。
signal(引數1,引數2);
第乙個引數signum:指明了所要處理的訊號型別,它可以取除了sigkill和sigstop外的任何一種訊號。
第二個引數handler:描述了與訊號關聯的動作,它可以取以下三種值:
(1)sig_ign
這個符號表示忽略該訊號。
例如:
#include
#include
intmain
(int argc,
char
*ar**)
sigint訊號代表由interruptkey產生,通常是ctrl +c 或者是delete 。執行上述**時,按下ctrl + c程式沒有反應。這就對了,如果我們想結束該程式可以按下ctrl +\來結束,當我們按下ctrl +\組合鍵時,產生了sigquit訊號,此訊號並沒有被忽略。
(2)sig_dfl
這個符號表示恢復對訊號的系統預設處理。不寫此處理函式預設也是執行系統預設操作。
例如
#include
#include
intmain
(int argc,
char
*ar**)
這時就可以按下ctrl +c 來終止該程序了。把signal(sigint, sig_dfl);這句去掉,效果是一樣的
(3)sighandler_t型別的函式指標上面提到了sighandler_t型別宣告:
typedef
void
(*sighandler_t)
(int
); sighandler_t signal
(int signum,
> sighandler_t handler)
;
此函式必須在signal()被呼叫前申明,handler中為這個函式的名字。當接收到乙個型別為sig的訊號時,就執行handler 所指定的函式。(int)signum是傳遞給它的唯一引數。執行了signal()呼叫後,程序只要接收到型別為sig的訊號,不管其正在執行程式的哪一部分,就立即執行func()函式。當func()函式執行結束後,控制權返回程序被中斷的那一點繼續執行。
例如
#include
#include
typedef
void
(*signal_handler)
(int);
void
signal_handler_fun
(int signum)
intmain
(int argc,
char
*ar**)
執行時,當我們按下ctrl +c鍵時,會執行我們定義的訊號處理函式。
catch signal 2
catch signal 2
catch signal 2
catch signal 2
=退出每當我們按下ctrl +c鍵時會列印該訊號的number.可以看出該訊號的num為2。要想退出可以按下ctrl +\ 列印結果為最後一行。
signal()會依引數signum 指定的訊號編號來設定該訊號的處理函式。當指定的訊號到達時就會跳轉到引數handler指定的函式執行。
當乙個訊號的訊號處理函式執行時,如果程序又接收到了該訊號,該訊號會自動被儲存而不會中斷訊號處理函式的執行,直到訊號處理函式執行完畢再重新呼叫相應的處理函式。但是如果在訊號處理函式執行時程序收到了其它型別的訊號,該函式的執行就會被中斷。
返回先前的訊號處理函式指標,如果有錯誤則返回sig_err(-1)。
Linux下訊號signal詳解
訊號又稱軟中斷訊號,是程序之間傳遞資訊的一種方式,訊號傳遞過程中不僅可以傳遞資訊,還可以附加傳遞一些資料資訊或其他內容.訊號按照可靠性可分為,可靠訊號和不可靠訊號 不可靠訊號 訊號傳遞過程中有可能丟失的訊號為不可靠訊號,在作業系統早期發展過程中,unix的訊號都是不可靠訊號,在後期發展過程中,lin...
linux 訊號 signal函式
include include include include include include include signal 函式有iso c定義,因為iso c 不涉及多執行緒 程序組以及終端i o等,所以它對訊號的定義非常含糊,以至於對於unix系統而言毫無作用。最好用sigactioan來代替...
Linux訊號機制 signal
linux下能夠通過訊號機制來實現程式的軟中斷。在程式執行的時候按下ctrl c ctrl z或者kill乙個程序的時候事實上都等效於向這個程序傳送了乙個特定訊號,當程序捕獲到訊號後,程序會被中斷並馬上跳轉到訊號處理函式。預設情況下乙個程式對ctrl c發出的訊號 sigint 的處理方式是退出程序...