Linux下的訊號signal的編寫

2021-10-25 07:49:35 字數 3337 閱讀 4135

對於 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 的處理方式是退出程序...