在linux系統當中有62個訊號,可以通過 kill -l 這個命令檢視如下圖所示
可以看到圖中的訊號分為兩個風格1-31是有獨自的名字,而34-64名字都是相同的。1-31是非實時訊號,34-64是實時訊號。關於訊號在man手冊中的第七本signal有詳細的說明。
signal:忽略訊號,捕捉訊號,恢復訊號預設預設動作函式
所需標頭檔案:
#include
函式原型:
typedef void (*sighandler_t)(int);
sighandler_t signal(int signum, sighandler_t handler);
引數說明:
signum:需要進行操作的訊號
handler:如果是乙個函式則捕捉到訊號後執行
sig_ign:忽略這個訊號
sig_dfl:預設執行這個訊號的預設動作
返回值:
返回訊號處理程式的先前值,sig_err則代表出錯並將錯誤原因寫入errno。
sigprocmask:阻塞訊號(將訊號掛起恢復訊號後執行動作)函式
所需標頭檔案:
#include
函式原型:
int sigprocmask(int how, const sigset_t *set, sigset_t *oldset);
引數說明:
how:
sig_block 新增訊號集合裡面的阻塞訊號
sig_unblock 解開阻塞
sig_setmask 覆蓋原本的設定,把set訊號集裡面的訊號設定到裡面去
set:訊號集合(需要設定的訊號的集合)
oldset:儲存舊的設定,不需要儲存則填null
返回值:
成功返回0,失敗返回-1並將錯誤原因寫入errno中。
訊號集的操作函式:
int sigemptyset(sigset_t *set);
清空訊號集中的所有訊號。
int sigfillset(sigset_t *set);
往訊號集中設定所有訊號。
int sigaddset(sigset_t *set, int signum);
往訊號集中新增訊號。
int sigdelset(sigset_t *set, int signum);
刪除訊號集中的成員。
int sigismember(const sigset_t *set, int signum);
判斷訊號是否在訊號集中。
非實時:能響應就響應,響應不了就丟掉。盡可能執行多個
非實時訊號有以下特點:
訊號有可能會丟失,非實時訊號的登記方式是通過程序結構體中的乙個標誌位(每個訊號對應著乙個二進位制數),通過這個標誌位來記錄訊號的個數,當接收到乙個訊號,在響應的過程中這時這個訊號的標誌位由0變為1。程序還未結束響應時,再次傳送同乙個訊號給程序時這個訊號的標誌位由0變為1,這時當函式還未結束時再去傳送n個相同的訊號都無法進行登記從而造成訊號的丟失。
巢狀響應(同乙個訊號不能連續巢狀),乙個程序在響應訊號的過程中會被另外的訊號打斷(非相同訊號),這時程序會響應後面這個訊號,響應完後面這個訊號後再回過頭去響應上乙個訊號,就是所謂的巢狀響應。
特定的響應模式,每個非實時響應訊號的預設預設動作都不相同且響應的事件也不相同有的例如sigint和sigquit,乙個預設預設動作是中斷,乙個預設預設是退出。
對應的名字和系統事件,非實時訊號與實時訊號相比比較明顯的一點就是名字。每個非實時訊號的名字有對應的名字且名字對應著系統事件(所實現的功能)。
響應的順序不確定,一般情況下是先來後到的順序,被堵塞時優先順序低於實時訊號。
實時:規定的時間響應完,且必定會響應。響應不了則報錯。先來先執行。
訊號不會丟失,實時訊號的登記方式是通過變數來登記的,同乙個變數可以登記多次不存在丟失的可能。
巢狀響應,同乙個訊號可以連續響應,響應方式與非實時 訊號相同。
響應的順序一般是先來後到的,只有在訊號被阻塞的時候才會有優先順序且由大到小。
忽略ctrl+c對程式的影響,當程式接收到訊號sigquit訊號的時候列印一句話。
#include
#include
#include
void
signal_fun
(int handler)
/*sigquit響應函式*/
intmain
(void)if
(sig_err ==
signal
(sigquit,signal_fun)
)/*捕捉sigquit訊號*/
while(1
)if(sig_err ==
signal
(sigint,sig_dfl)
)/*恢復sigint訊號*/
return0;
}
編寫一段程式,建立兩個子程序:
用signal讓父程序捕捉sigint,
當捕獲到sigint後,父程序用kill向兩個子程序分別發訊號,
傳送sigusr1給子程序1, 傳送sigusr2給子程序2
子程序捕捉到父程序發來的訊號後,分別輸入下列資訊後終止
child process 1 is killed by parent!
child process 2 is killed by parent!
父程序等待兩個子程序終止後,輸出以下資訊後終止
parent process exit!
#include
#include
#include
#include
#include
#include
#include
int retvel[2]
,status;
void
signal_fun
(int handler)
/*sigint響應函式*/
void
signal_fun1
(int handler)
void
signal_fun2
(int handler)
intmain
(void
)pause()
;/*暫停函式,遇到任意乙個訊號則繼續下一步*/
exit
(exit_success)
;/*正常退出*/}
retvel[1]
=fork()
;/*建立第二個子程序*/
if(retvel[1]
==0)pause()
;/*暫停函式,遇到任意乙個訊號則繼續下一步*/
exit
(exit_success)
;/*正常退出*/}if
(sig_err ==
signal
(sigint,signal_fun)
)/*注意:此處定義捕捉中斷訊號將不被子程序所繼承,定義在程式開頭將會被子程序繼承將會造成別的結果*/
for(
int i=
0;i<
2;i++
)printf
("parent process exit!\n");
return0;
}
編寫乙個程式,該程式規定sigint這個訊號接收的時候,每隔一秒列印一句hello,
其他所有的訊號都不能打斷sigint的響應函式(不能巢狀響應)(signal跟sigprocmask兩個函式做)
#include
#include
#include
void
signal_fun
(int handler)
/*中斷響應函式*/
sigprocmask
(sig_unblock,
&set_signal,
null);
/*執行完後清除阻塞*/
}int
main
(void
)while(1
)return0;
}
ps -aux
檢視程序狀態
pstree
以樹狀的形式檢視程序狀態
kill -s 引數1 引數2
引數1:指定傳送的訊號
引數2:指定接收的程序號
kill 程序號
預設傳送sigquit訊號退出程式
有兩個特殊的訊號無法被忽略、堵塞或捕捉
sigkill(殺死) sigstop(暫停)
這裡是乙隻正在努力的菜鳥,如果有**寫的不對的地方,希望各位大佬多多指正,我會加以改進!
linux程序間通訊之訊號
1 wait 函式 原型 pid t wait int status 子程序退出時,它向父程序傳送乙個sigchld訊號,預設情況是總是忽略sigchld訊號,此時程序狀態一直保留在記憶體中,因此需要父程序去處理改訊號,處理的辦法則是呼叫wait 函式,收集子程序狀態資訊,並清空該資訊 使用wait...
Linux訊號 程序間非同步的通訊機制
一 概念和功能 訊號實際上是乙個軟中斷,用於通知程序發生了某些事,該如何處理。實際上也歸為一類程序間通訊方式,訊號的生命週期 訊號的產生 訊號的註冊 訊號的阻塞 遮蔽 訊號的登出 訊號的處理 二 檢視訊號 kill l 檢視linux下全部訊號,可看出訊號是由編號和巨集組成 kill並不是殺死乙個程...
程序間通訊之訊號
訊號是軟體中斷。很多比較重要的應用程式都需要處理訊號。訊號提供了一種處理非同步事件的方法。每個訊號都有乙個名字,並且他們的名字都是以sig開頭的。訊號的處理或相關動作有三種處理方式 1 預設訊號 sig dfl 2 忽略訊號 sig ign 大多數訊號可採用,除sigkill和sigstop外。3 ...