Linux下訊號signal詳解

2021-10-25 09:29:51 字數 2450 閱讀 5899

訊號又稱軟中斷訊號,是程序之間傳遞資訊的一種方式,訊號傳遞過程中不僅可以傳遞資訊,還可以附加傳遞一些資料資訊或其他內容.

訊號按照可靠性可分為,可靠訊號和不可靠訊號

不可靠訊號:訊號傳遞過程中有可能丟失的訊號為不可靠訊號,在作業系統早期發展過程中,unix的訊號都是不可靠訊號,在後期發展過程中,linux在不可靠訊號的基礎上發展出了可靠訊號,但因版本相容問題,不可靠訊號也在一直沿用.

可靠訊號:訊號傳輸過程中不會丟失的訊號.

訊號按照時間關係還可分為實時訊號和非實時訊號

實時訊號和非實時訊號的區別同樣是是否支援排列,簡單來說,所有的可靠訊號都是實時訊號,所有的不可靠訊號都是非實時訊號.

在linux命令列可以用kill -l列出當前版本作業系統註冊的訊號,不同版本的作業系統可能會列出不同的訊號.

在程式中如何給指定程序傳送訊號

int kill(pid_t pid,int sig);通過kill函式給指定程序傳送特定訊號,kill函式第乙個引數為指定程序的pid,若第乙個引數為0時,則表示給當前程序程序組所有程序傳送訊號,當pid為-1時,則表示給當前程序使用者有許可權的除1號程序外所有程序傳送訊號.第二個引數為要傳送的訊號.

int raise(int sig);通過raise函式給當前程序傳送乙個sig訊號.

在程式中如何指定訊號的處理方式

在訊號抵達時,作業系統提供了三種解決方式,第一種為預設按作業系統預設解決方案解決,第二種是遮蔽訊號,不進行處理,第三種是使用者自己指定解決方案.

void(*signal(int sig,void (*handler)(int)))(int);

給sig訊號指定乙個解決方案,第乙個引數為訊號常量,第二個引數為乙個函式指標,指向要修改訊號的解決方案

int sigaction(int signum,const struct sigaction *act ,struct sigaction *oldact);

給sig訊號指定解決方案,並返回舊的解決方案.

第乙個引數為指定的訊號常量,第二個引數為乙個sigaction結構體,內部儲存新的解決方案,第三個引數為需要返回的舊的結構體.

sigaction結構體內部展開為:

struct sigaction
結構體中第一和第二個都是訊號處理函式指標,具體應用哪個取決於sa_flags標誌,預設情況下使用第乙個函式.sa_mask 用來設定在處理該訊號時暫時將sa_mask 指定的訊號集擱置,sa_flags為乙個可設定的標記位,用於訊號設定時其他選項,這裡不做詳解.

作業系統內部設定了三個集合來分別表示訊號是否被遮蔽,訊號是否未決和訊號的解決函式.

上述指定訊號處理方式的內部實現其實就是更改了作業系統內部訊號解決函式集合的內容.

如果想要遮蔽某些訊號,就可以更改阻塞訊號集,如何更改阻塞訊號集,可以呼叫sigprocmask()函式來解決.

int sigprocmask(int how, const sigset_t *restrict set, sigset_t *restrict oldset);

第乙個引數是乙個選項引數,可設定的選項有:

1.sig_block: 將set中的訊號加入到原有的阻塞訊號集中作為阻塞訊號.

2.sig_unblock:將set中的訊號從阻塞訊號集中移除,設定為非阻塞訊號.

3.sig_setmask:設定當前訊號掩碼為引數set中的訊號。

第二個引數為需要設定訊號的訊號集,最後乙個引數為需要返回的舊的阻塞訊號集.

如何設定乙個訊號集

訊號集的型別是struct sigset_t,首先申請一塊sigset_t的空間並通過sigemptyset()清空空間,之後通過sigaddset()函式向訊號集中新增訊號.

下面舉例出相關訊號集操作函式:

int sigemptyset(sigset_t *set);將傳入的sigset_t型別資料清空.

int sigaddset(sigset_t *set,int signum);將訊號signum新增進set訊號集中.

int sigfillset(sigset_t * set);將所有訊號新增進訊號集set中.

int sigdelset(sigset_t * set,int signum);從訊號集set中刪除訊號signum訊號.

int sigismember(const sigset_t *set,int signum);檢測set訊號集中是否存在signum訊號.

前面說過,作業系統中存在三個集合,第乙個是阻塞訊號集,第二個為訊號處理函式指標集合,最後乙個為訊號未決集合.

什麼是未決訊號呢,在linux中訊號從產生,到**獲,再到被處理,中間需要經過很多步驟,而當乙個訊號產生之後,若該訊號被遮蔽掉,就不會被處理函式處理,這時該訊號就稱為未決訊號,未決訊號會被放置在未決訊號集裡.

我們可以根據sigpending()函式來獲取未決訊號集中的未決訊號,可進行額外處理.

int sigpending(sigset_t *set);返回未決訊號集中的未決訊號.

Linux下的訊號signal的編寫

對於 linux來說,實際訊號是軟中斷,許多重要的程式都需要處理訊號。訊號,為 linux 提供了一種處理非同步事件的方法。比如,終端使用者輸入了 ctrl c 來中斷程式,會通過訊號機制停止乙個程式。1 訊號的名字和編號 每個訊號都有乙個名字和編號,這些名字都以 sig 開頭,例如 sigio s...

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