使用sigaction函數


sigaction函數

修改信號處理動作(通常在Linux用其來注冊一個信號的捕捉函數)

int sigaction(int signum, const struct sigaction *act, struct sigaction *oldact);  成功:0;失敗:-1,設置errno

參數:

act:傳入參數,新的處理方式。oldact:傳出參數,舊的處理方式。

struct sigaction結構體

    struct sigaction {

    void(*sa_handler)(int);

    void(*sa_sigaction)(int, siginfo_t *, void *);

    sigset_t sa_mask;

    int sa_flags;

    void(*sa_restorer)(void);

};

sa_restorer:該元素是過時的,不應該使用,POSIX.1標准將不指定該元素。(棄用)

sa_sigaction:當sa_flags被指定為SA_SIGINFO標志時,使用該信號處理程序。(很少使用)

重點掌握:

sa_handler:指定信號捕捉后的處理函數名(即注冊函數)。也可賦值為SIG_IGN表忽略 SIG_DFL表執行默認動作

sa_mask: 調用信號處理函數時,所要屏蔽的信號集合(信號屏蔽字)。注意:僅在處理函數被調用期間屏蔽生效,是臨時性設置。用sigaddset函數添加需要被捕捉的信號。

sa_flags:通常設置為0,表使用默認屬性:為0的時候,可以屏蔽正在處理的信號(若在處理2號信號時又有2號信號,則此時傳來的2號信號會被屏蔽)。

不多說了,上代碼:

#include <stdlib.h>

#include <stdio.h>

#include <signal.h>

void func(int signal)

{

    printf("%d號信號被捕捉。\n", signal);

}

int main(void)

{

    struct sigaction act, oldact;

    act.sa_handler = func;

    act.sa_flags = 0;//為0的時候,可以屏蔽正在處理的信號(若在處理2號信號時又有2號信號,則>會被屏蔽)

    sigemptyset(&act.sa_mask);//sa_mask是一個臨時信號集,將其清零(初始化I)

    sigaddset(&act.sa_mask, SIGQUIT);//將3號信號添加到信號集,即:3號信號就是我們在處理2號信號的時候需要屏蔽的那個信號,也許可以添加其他信號,比如20號信號

    sigaddset(&act.sa_mask, SIGTSTP);

    int s_ret = sigaction(SIGINT, &act, &oldact);

    if (0>s_ret)

    {

        perror("sigaction error");

        exit(1);

    }

    while (1);

    return 0;

}

結果:我的環境是win10子系統,經過我的測試,ctrl+\這個組合鍵不被支持,不能發送3號信號。所以在我按下ctrl+\之后並沒有反應,程序依舊執行,但是在真正的Linux獨立系統中,按下之后該程序會被殺掉的,就如同我按下ctrl+z之后,程序掛起:接下來kill掉就是了。

   

———————————————隔了不到十分鍾又來更新的分割線——————————————-

我們來看看信號捕捉特性

進程正常運行時,默認PCB中有一個信號屏蔽字,假定為,它決定了進程自動屏蔽哪些信號。當注冊了某個信號捕捉函數,捕捉到該信號以后,要調用該函數。而該函數有可能執行很長時間,在這期間所屏蔽的信號不由來指定。而是用sa_mask來指定。調用完信號處理函數,再恢復為

XXX信號捕捉函數執行期間,XXX信號自動被屏蔽。

阻塞的常規信號不支持排隊,產生多次只記錄一次。(后32個實時信號支持排隊)

為了模擬這個3所說的內容,我們這樣改代碼:

void func(int signal)

{

    printf("%d號信號被捕捉。\n", signal);

    sleep(5);//睡眠十秒,模擬處理信號的函數處理時間很長的那種情況

    puts("———————————— - fiish———————");

}

我的測試結果:

第一次只按一次ctrl+c,顯示被捕捉之后瘋狂的按ctrl+cfinish之后顯示信號再次被捕捉,然后瘋狂按ctrl+cctrl+z。結果是:那么多次的ctrl+c只執行了三次,多次的ctrl+z也只是被執行了一次。其實原理很好理解的,我們知道,當信號被阻塞時,未決信號集中的相應編號的位置會有0翻轉為1,信號集是什么?是位圖。他不能為多次的相同的信號計數。所以,再多的相同信號在系統看來也只是一個罷了。

————————————–再更新一次————————————-

signal()sigaction()函數是捕捉信號的函數么?是么?是么?是么?

不是,他倆只是注冊信號捕捉函數的函數,真正動手捉信號的是內核。記得啊。本質區別的。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM