0x00
訊號和中斷類似,中斷是硬體發出,而訊號由軟體發出。
訊號常用於程序間通訊,乙個訊號常見的處理如下:
1、設定對應訊號的訊號處理函式。
2、當訊號來臨時,打斷正常執行的程式(本質上是在系統呼叫前檢查是否有訊號的到來),去執行訊號處理函式。
3、訊號處理函式執行完,繼續執行原程式。
0x01
我們先來看一下linux中一共支援多少種訊號。使用命令kill -l,可以列出linux支援的所有訊號。
每個訊號都有對應的預設訊號處理函式,使用命令man 7 signal,可以檢視到。
如果訊號沒有定義對應的訊號處理函式,並且沒有忽略訊號,那麼則採用預設的訊號處理函式。
這裡要注意,訊號sigkill和sigstop既不能**捉,也不能被忽略。
0x02
我們看乙個自定義訊號處理函式的例子,來學習如何自定義訊號處理,並且學習如何傳送訊號。
#include #include #include #include #include #include #include #include #include #include #define err_exit(m) \
do \
while(0)
void handler(int sig);
int main(int argc, char *argv)
void handler(int sig)
這個程式中我們自定義了訊號處理函式,對應的訊號是sigint,那麼什麼時候會傳送這個這個訊號呢?答案是當使用者按下ctrl + c時,我們看控制台輸出的結果。
對照訊號表,sigint是2號訊號。在程式中pause,可以用來等待下一次訊號的來臨。
在這個例子中傳送訊號是通過鍵盤按ctrl + c。
這裡順便說一下三號訊號sigquit,傳送該訊號,按鍵盤ctrl + \。
0x03
我們接著講另一種傳送訊號的方式,通過kill,列出**:
#include #include #include #include #include #include #include #include #include #include #define err_exit(m) \
do \
while(0)
void handler(int sig);
int main(int argc, char *argv)
int n = 5; //父程序
do while (n > 0);
return 0;
}void handler(int sig)
這個程式中使用了sigusr1這個使用者自定義訊號。使用kill向對應的父程序傳送訊號,父程序sleep一旦接收到訊號,會立刻退出,所以就不會睡眠5秒鐘,那麼如何讓父程序睡眠5秒鐘呢?我們採用了迴圈的方式,即使被子程序發來的訊號打斷,也可以繼續睡眠剩餘的時間。
這個例子中傳送訊號,我們採用kill的方式。
0x04
下面再看乙個通過alarm傳送訊號的例子:
#include #include #include #include #include #include #include #include #include #include #define err_exit(m) \
do \
while(0)
void handler(int sig);
int main(int argc, char *argv)
void handler(int sig)
通過alarm函式向自身程序傳送sigalrm的訊號,在訊號處理函式中再一次傳送alrm訊號,起到了乙個定時器的作用。
0x05
接下來的例子,我們講解下結束程序的幾種方式,結合waitpid函式,進一步理解waitpid函式。
#include #include #include #include #include #include #include #include #include #include #define err_exit(m) \
do \
while(0)
int main(int argc, char *argv)
int ret;
printf("this is parent\n");
int status;
//ret = wait(&status);
//ret = waitpid(-1, &status, 0);
ret = waitpid(pid, &status, 0); //父程序
printf("ret = %d pid = %d\n", ret, pid);
if (wifexited(status))
printf("child exited normal exit status=%d\n", wexitstatus(status));
//else
// printf("child exited abnormal\n");
else if (wifsignaled(status))
printf("child exited abnormal signal number=%d\n", wtermsig(status));
else if (wifstopped(status))
printf("child stoped signal number=%d\n", wstopsig(status));
return 0;
}
這個例子說明了結束乙個程序的幾種方式:
1、exit(100) ---> 控制台輸出:child exited normal exit status=100
2、return 0 ---> 控制台輸出:child exited normal exit status=0
3、abort(),向當前程序傳送sigabrt,sigabrt訊號的預設處理函式為終止程序 ---> 控制台輸出:
child exited abnormal signal number=6 (sigabrt是6號訊號)
4、raise(sigkill),向當前程序傳送sigkill訊號,sigkill訊號的預設處理函式是終止程序 --> 控制台輸出:child exited abnormal signal number=9 (sigkill是9號訊號)
0x06
總結:訊號既可以**獲(自定義訊號處理函式),也可以忽略,也可以走預設訊號處理函式。
傳送訊號有以下幾種方式:
1、鍵盤操作,ctrl + c,ctrl + \
2、kill
3、alarm
4、abort
5、raise
Linux系統程式設計 訊號
基本概念 訊號的狀態 產生未決狀態 沒有被處理的 遞達 已經被處理的 訊號的優先順序比較高 程序收到訊號之後,暫停正在處理的工作 訊號集 kill 發射訊號給某個程序 raise 自己給自己發訊號 函式原型 int raise int sig abort 給自己傳送異常終止的訊號 alarm 設定定...
Linux系統程式設計 訊號
訊號的共性 1.簡單 2.不能攜帶大量資訊 3.滿足特定條件才能傳送 訊號的機制 1.訊號是軟體層面的中斷。一旦訊號產生,無論程式執行到什麼位置都必須結束 2.所有訊號的產生以及處理都是核心產生.訊號的產生 1.按鍵產生 程ctrl c ctrl v 2.系統呼叫產生 kill函式 3.定時器 al...
Linux系統程式設計 訊號
訊號處理雖然初學者用的不會很多,而且現有太多對訊號的替代品。但作為乙個打算專精發展的coder來說,還是必須學習和掌握的。linux下,乙個程序給其他程序傳送訊號的api是kill函式 include include intkill pid t pid,int sig sig 引數決定了要傳送的訊號...