linux學習筆記之訊號

2021-07-23 06:30:37 字數 4270 閱讀 5731

訊號機制是程序之間想回傳遞訊息的一種方法,應用於非同步事件的處理,訊號全稱為軟中斷訊號,它被傳送給乙個正在被執行的程序以通知該程序有某一件事發生。

發出訊號的原因有很多:

1.與程序終止有關的訊號。當程序退出或子程序終止時,會發出這類訊號

2.與程序列外事件相關的訊號。如程序越界,或企圖寫乙個唯讀的記憶體區域,或其它各種硬體錯誤。

3.與在系統呼叫期間遇到不可恢復條件相關的訊號。如執行系統呼叫exec時,原有資源已經釋放,而目前的資源又已經耗盡。

4.與執行系統呼叫時遇到非**錯誤條件相關的訊號。如執行乙個並不存在的系統呼叫

5.在使用者態下的程序發出的訊號。如程序呼叫系統呼叫kill向其他程序傳送訊號

6.與終端互動相關的訊號。如使用者關閉乙個終端..

7.跟蹤程序執行的訊號

在linux裡面每個程序都是按照程序描述符 task_struct 結構建立的,還有乙個叫task vector的東西,從名字上就能看出來這是乙個陣列,這裡面儲存的是指向每乙個程序的指標,即指向每乙個task_struct的指標,因此乙個linux系統最大的程序數,取決於task vector這個陣列的大小,一般預設是512個。在程序描述符task_struct裡面,其中一項是signal_strct,在signal_strct這裡面有一項list_head的描述符,在這裡面有乙個sigset_t表,定義了64種訊號的所代表的含義。(訊號列表)也就是說在每個程序之中,都有存著乙個表,裡面存著每種訊號所代表的含義,而這也是訊號機制的根本。由於訊號的觸發和傳送是隨機的,也就是非同步的。接收程序是無法預知什麼時間,會收到哪個訊號的。下面就開始講下訊號的詳細傳送機制,舉例說明,如果有a,b兩個程序,a程序接收到出發條件,開始傳送訊號給b程序,訊號並不是直接從程序a傳送給程序b,而是要通過核心來進行**。之所以要通過核心來**,這樣做的目的應該也是為了對程序的管理和安全因素考慮。因為在這些訊號當中,sigstop和sigkill這兩個訊號是可以將接收此訊號的程序停掉的,而這類訊號,肯定是需要有許可權才可以發出的,不能夠隨便哪個程式都可以隨便停掉別的程序。a程序傳送的訊號訊息,其實就是根據上面的那個訊號表,根據需要對相應的表項進行設定。核心接受到這個訊號訊息後,會先檢查a程序是否有許可權對b程序的訊號表對應的項進行設定,如果可以,就會對b程序的訊號表進行設定,這裡面訊號處理有個特點,就是沒有排隊的機制,也就是說某個訊號被設定之後,如果b程序還沒有來及進行響應,那麼如果後續第二個同樣的訊號訊息過來,就會被阻塞掉,也就是丟棄。核心對b程序訊號設定完成後,就會傳送中斷請求給b程序,這樣b程序就進入到核心態,這個時候程序b根據那個訊號表,查詢對應的此訊號的處理函式,然後設定frame,設定好之後,跳回到使用者態執行訊號處理函式,處理完成後,再次返回到核心態,再次設定frame,然後再次返回使用者態,從中斷位置開始繼續執行。這個frame其實就是在使用者態和核心態之間跳轉的時候,對堆疊現場的壓棧儲存。

linux下程序的訊號處理大概就是這麼乙個過程,在真正使用的時候,就比較簡單了,用kill函式傳送訊號,在接收程序裡,通過signal或者signalaction函式呼叫sighandler(處理函式),來啟動對應的函式處理訊號訊息。

kill函式

函式原型 int kill(pid_t,int signum); // 成功返回0,否則返回-1

pid>0 將訊號傳送給程序號為pid的程序

pid=0 將訊號傳送給當前程序所在程序組的所有程序

pid<0&&pid!=-1 向id為pid絕對值的程序組中的所有程序傳送訊號

pid=-1 除自身外向所有程序id大於1的程序傳送訊號

signum代表傳送的訊號,參見訊號列表。signum為0時不傳送任何訊號,但照常進行錯誤檢查,可用於檢查目標程序是否存在以及當前程序是否有向目標程序傳送訊號的許可權。

父程序向其子程序傳送sigabrt訊號使子程序非正常結束

#include

#include

#include

#include

#include

int main()

else

wait(&status);

if(wifsignaled(status))

}return

0;}

類似的傳送訊號函式還有

int raise(int signum); //signum為將要傳送的訊號值

int sigqueue(pid_t pid,int signum,const union sigval val); //pid為指定程序的id signum為要傳送的訊號值,第三個引數指定了傳遞的引數

unsigned int alarm(unsigned int seconds); //此函式專為sigalrm訊號而設 使系統在一定時間後傳送訊號

int setitimer(int which,const struct itimerval *value,struct itimerval *oldvalue); //與alarm函式類似 也可以使系統在某一時刻傳送訊號,但更精確。

void abort(void); // 想程序傳送sigabort訊號,預設情況下程序會異常退出

signal函式

通過呼叫signal函式來註冊某個特定訊號的處理程式,函式原型

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

如果signal()呼叫成功,返回最後一次為安裝訊號signum而呼叫signal()時的handler值;失敗則返回sig_err。

posix定義:

typedef void(*sighandler_t)(int);

signhandler_t signal(int signum,sighandler_t handler);

但這種格式在不同的系統中有不同的定義。第乙個引數指定訊號的值,第二個引數指定針對前面訊號值的處理,可以忽略該訊號(引數設為sig_ign);sigstop/sigkill這倆訊號無法捕獲和忽略,可以採用系統預設方式處理訊號(引數設為sig_dfl);也可以自己實現處理方式(引數指定乙個函式位址)。

/*實現程序的軟中斷通訊*/

/*按ctrl+c鍵,可傳送sigint訊號給當前程序*/

/*使用系統呼叫fork()建立兩個子程式,再用系統呼叫signal()註冊父程序和子程序分別對待從鍵盤上來的中斷訊號(sigint訊號)的行為;當有中斷訊號後,父程序用系統呼叫kill()向兩個子程序發出訊號,子程序收到訊號後分別輸出

child processll is killed by parent!

child processl2 is killed by parent!

父程序等待兩個子程序終止後,輸出如下的資訊後終止:

parent process is killed!

*/#include

#include

#include

int wait_mark;

void waiting()

void stop()

int main()

else

else

}

sigaction函式

此函式的功能是修改或檢查與指定訊號相關聯的處理動作,函式原型

int sigaction(int signum,const struct sigaction *act,struct sigaction *oldact); //成功返回0 出錯返回-1 。引數signum為需要捕捉的訊號。函式act是乙個結構體。包含的資訊如下:

struct sigaction
/*sigaction系統呼叫的使用方法。sigaction函式的功能是檢查或修改與制定訊號相關聯的處理動作,可以完全代替signal函式*/

#include

#include

#include

#include

int g_iseq=0;

void signhandlernew(int isignno,siginfo_t *pinfo,void *preserved)

int main(void)

szbuf[iret]=0;

printf("get: %s",szbuf); /*列印終端輸入的字串*/

}while(strcmp(szbuf,"quit\n")!=0); /*輸入"quit"時退出程式*/

return

0;}

linux學習筆記之訊號量

訊號量機制 判斷是否具有可用資源 可用資源 訊號 訊號量值為1 的訊號 linux 執行緒的訊號量 簡稱 二值訊號量 訊號量的值 0,1 訊號量的使用框架 建立訊號量 初始化訊號量 pv操作 訊號量的銷毀 0 標頭檔案 include 1 建立訊號量 全域性定義乙個 sem t 型別的變數 2 初始...

Linux學習筆記2 訊號

訊號是事件發生時對程序的通知機制,也被稱為軟中斷。大多數情況下,無法 訊號到達的精確時間。乙個 具有合適許可權的 程序能夠向另一程序傳送訊號。程序也可以向自身傳送訊號。然而,發往程序的諸多訊號,通常有源於核心。引發核心為程序產生訊號的各類事件如下。訊號產生後,會於稍後被傳遞給某一程序,而程序也會採取...

linux之通訊之訊號學習1

比如我們按下了鍵盤或者其它硬體故障 軟體 最常用傳送訊號的系統函式是kill,raise,alarm 和setitimer 以及sigqueue 函式,軟體 還包括一些非法運算等操作。程序可以通過三種方式來響應乙個訊號 1 忽略訊號,即對訊號不做任何處理,其中,有兩個訊號不能忽略 sigkill 及...