linux 訊號機制

weixin_34393428發表於2019-01-14

1. Linux支援的訊號列表如下。很多訊號是與機器的體系結構相關的

訊號值 預設處理動作 發出訊號的原因

SIGHUP 1 A 終端掛起或者控制程式終止

SIGINT 2 A 鍵盤中斷(如break鍵被按下)

SIGQUIT 3 C 鍵盤的退出鍵被按下

SIGILL 4 C 非法指令

SIGABRT 6 C 由abort(3)發出的退出指令

SIGFPE 8 C 浮點異常

SIGKILL 9 AEF Kill訊號

SIGSEGV 11 C 無效的記憶體引用

SIGPIPE 13 A 管道破裂: 寫一個沒有讀埠的管道

SIGALRM 14 A 由alarm(2)發出的訊號

SIGTERM 15 A 終止訊號

SIGUSR1 30,10,16 A 使用者自定義訊號1

SIGUSR2 31,12,17 A 使用者自定義訊號2

SIGCHLD 20,17,18 B 子程式結束訊號

SIGCONT 19,18,25 程式繼續(曾被停止的程式)

SIGSTOP 17,19,23 DEF 終止程式

SIGTSTP 18,20,24 D 控制終端(tty)上按下停止鍵

SIGTTIN 21,21,26 D 後臺程式企圖從控制終端讀

SIGTTOU 22,22,27 D 後臺程式企圖從控制終端寫

2. 建立訊號集

sigset_t initset;
sigemptyset(&initset);//初始化訊號集合為空集合
sigaddset(&initset,SIGINT);//將SIGINT訊號加入到此集合中去
sigprocmask(SIG_BLOCK,&initset,NULL);//將訊號集合加入到程式的阻塞集合中去 失敗返回-1

//建立一個fd進行監聽
int create_signal_fd ( void )
{
    sigset_t attention_signal;
    sigemptyset ( &attention_signal );
    sigaddset ( &attention_signal,SIGPIPE );
    return sigprocmask ( SIG_BLOCK, &attention_signal,NULL ) < 0 ? -1 : signalfd ( -1,&attention_signal,SFD_CLOEXEC );
}

//監聽fd,根據產生中的訊號做相應處理
signalfd_siginfo signal_buf;
if ( signal_buf.ssi_signo==SIGPIPE ) {
    LOG(INFO) <<"get SIGPIPE";
}

3. 簡單的訊號處理函式signal()

#include <signal.h>
void (signal(int signum, void (handler))(int)))(int);

如果該函式原型不容易理解的話,可以參考下面的分解方式來理解:

typedef void (*sighandler_t)(int);

sighandler_t signal(int signum, sighandler_t handler));

第一個引數指定訊號的值,第二個引數指定針對前面訊號值的處理,可以忽略該訊號(引數設為SIG_IGN);可以採用系統預設方式處理訊號(引數設為SIG_DFL);也可以自己實現處理方式(引數指定一個函式地址)。

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

傳遞給訊號處理例程的整數引數是訊號值,這樣可以使得一個訊號處理例程處理多個訊號。

#include <signal.h>

#include <unistd.h>

#include <stdio.h>

void sigroutine(int dunno)

{ /* 訊號處理例程,其中dunno將會得到訊號的值 */

        switch (dunno) {

        case 1:

        printf("Get a signal -- SIGHUP ");

        break;

        case 2:

        printf("Get a signal -- SIGINT ");

        break;

        case 3:

        printf("Get a signal -- SIGQUIT ");

        break;

        }

        return;

}

 

int main() {

        printf("process id is %d ",getpid());

        signal(SIGHUP, sigroutine); //* 下面設定三個訊號的處理方法

        signal(SIGINT, sigroutine);

        signal(SIGQUIT, sigroutine);

        for (;;) ;

}

 

//其中訊號SIGINT由按下Ctrl-C發出,訊號SIGQUIT由按下Ctrl-發出。該程式執行的結果如下:

localhost:~$ ./sig_test

process id is 463

Get a signal -SIGINT //按下Ctrl-C得到的結果

Get a signal -SIGQUIT //按下Ctrl-得到的結果

//按下Ctrl-z將程式置於後臺

 [1]+ Stopped ./sig_test

localhost:~$ bg

 [1]+ ./sig_test &

localhost:~$ kill -HUP 463 //向程式傳送SIGHUP訊號

localhost:~$ Get a signal – SIGHUP

kill -9 463 //向程式傳送SIGKILL訊號,終止程式

localhost:~$

相關文章