信號(hào)處理函數(shù)

信號(hào)處理函數(shù)


sigaction的用法

int sigaction (

????????int signo,

????????const struct sigaction *act,

????????struct sigaction *oldact

);

這個(gè)函數(shù)主要是用于改變或檢測(cè)信號(hào)的行為。

第一個(gè)參數(shù)是變更signo指定的信號(hào),它可以指向任何值,SIGKILL,SIGSTOP除外

第二個(gè)參數(shù),第三個(gè)參數(shù)是對(duì)信號(hào)進(jìn)行細(xì)粒度的控制。

如果*act不為空,*oldact不為空,那么oldact將會(huì)存儲(chǔ)信號(hào)以前的行為。

如果act為空,*oldact不為空,那么oldact將會(huì)存儲(chǔ)信號(hào)現(xiàn)在的行為。

struct sigaction? {

????????void (*sa_handler)(int);

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

????????sigset_t sa_mask;

????????int sa_flags;

????????void (*sa_restorer)(void);

}

參數(shù)含義:

sa_handler是一個(gè)函數(shù)指針,主要是表示接收到信號(hào)時(shí)所要采取的行動(dòng)。此字段的值可以是SIG_DFL,SIG_IGN.分別代表默認(rèn)操作與內(nèi)核將忽略進(jìn)程的信號(hào)。這個(gè)函數(shù)只傳遞一個(gè)參數(shù)那就是信號(hào)代碼。

當(dāng)SA_SIGINFO被設(shè)定在sa_flags中,那么則會(huì)使用sa_sigaction來(lái)指示信號(hào)處理函數(shù),而非sa_handler.

sa_mask設(shè)置了掩碼集,在程序執(zhí)行期間會(huì)阻擋掩碼集中的信號(hào)。

sa_flags設(shè)置了一些標(biāo)志, SA_RESETHAND當(dāng)該函數(shù)處理完成之后,設(shè)定為為系統(tǒng)默認(rèn)的處理模式。SA_NODEFER 在處理函數(shù)中,如果再次到達(dá)此信號(hào)時(shí),將不會(huì)阻塞。默認(rèn)情況下,同一信號(hào)兩次到達(dá)時(shí),如果此時(shí)處于信號(hào)處理程序中,那么此信號(hào)將會(huì)阻塞。

SA_SIGINFO表示用sa_sigaction指示的函數(shù)。

sa_restorer已經(jīng)被廢棄。

sa_sigaction所指向的函數(shù)原型:

void my_handler(int signo, siginfo_t *si, void *ucontext);

第一個(gè)參數(shù): 信號(hào)編號(hào)

第二個(gè)參數(shù):指向一個(gè)siginfo_t結(jié)構(gòu)。

第三個(gè)參數(shù)是一個(gè)ucontext_t結(jié)構(gòu)。

其中siginfo_t結(jié)構(gòu)體中包含了大量的信號(hào)攜帶信息,可以看出,這個(gè)函數(shù)比sa_handler要強(qiáng)大,因?yàn)榍罢咧荒軅鬟f一個(gè)信號(hào)代碼,而后者可以傳遞siginfo_t信息。

typedef struct siginfo_t {

????????int si_signo;//信號(hào)編號(hào)

????????int si_errno;//如果為非零值則錯(cuò)誤代碼與之關(guān)聯(lián)

????????int si_code;//說(shuō)明進(jìn)程如何接收信號(hào)以及從何處收到

????????pid_t si_pid;//適用于SIGCHLD,代表被終止進(jìn)程的PID

????????pid_t si_uid;//適用于SIGCHLD,代表被終止進(jìn)程所擁有進(jìn)程的UID

????????int si_status;//適用于SIGCHLD,代表被終止進(jìn)程的狀態(tài)

????????clock_t si_utime;//適用于SIGCHLD,代表被終止進(jìn)程所消耗的用戶時(shí)間

????????clock_t si_stime;//適用于SIGCHLD,代表被終止進(jìn)程所消耗系統(tǒng)的時(shí)間

????????sigval_t si_value;

????????int si_int;

????????void * si_ptr;

????????void* si_addr;

????????int si_band;

????????int si_fd;

};

sigqueue的用法

sigqueue( pid_t pid, int signo, const union sigval value)

union sigval? {int sival_int, void*sival_ptr };

sigqueue函數(shù)類似于kill,也是一個(gè)進(jìn)程向另外一個(gè)進(jìn)程發(fā)送信號(hào)的。

但它比kill函數(shù)強(qiáng)大。

第一個(gè)參數(shù)指定目標(biāo)進(jìn)程的pid.

第二個(gè)參數(shù)是一個(gè)信號(hào)代碼。

第三個(gè)參數(shù)是一個(gè)共用體,每次只能使用一個(gè),用來(lái)進(jìn)程發(fā)送信號(hào)傳遞的數(shù)據(jù)。

或者傳遞整形數(shù)據(jù),或者是傳遞指針。

發(fā)送的數(shù)據(jù)被sa_sigaction所指示的函數(shù)的siginfo_t結(jié)構(gòu)體中的si_ptr或者是si_int所接收。

sigpending的用法

sigpending(sigset_t set);

這個(gè)函數(shù)的作用是返回未決的信號(hào)到信號(hào)集set中。

即未決信號(hào)集,未決信號(hào)集不僅包括被阻塞的信號(hào),也可能包括已經(jīng)到達(dá)但沒(méi)有被處理的信號(hào)。

示例1: sigaction函數(shù)的用法

void signal_set1(int x) { //信號(hào)處理函數(shù),只傳遞一個(gè)參數(shù)信號(hào)代碼

????????printf("xxxxx/n");

????????while(1)? {

????????????????//

?????????}

}

void signal_set(struct sigaction *act)

{

????????switch(act->sa_flags) {

????????case (int)SIG_DFL:

????????????????printf("using default hander/n");

????????????????break;

????????case (int)SIG_IGN:

????????????????printf("ignore the signal/n");

????????????????break;

????????default:

????????????????printf("%0x/n",act->sa_handler);

????????}

}

int main(int argc, char** argv)

{

????????int i;

????????struct sigaction act,oldact;

????????act.sa_handler = signal_set1;

????????act.sa_flags = SA_RESETHAND;

????????//SA_RESETHANDD 在處理完信號(hào)之后,將信號(hào)恢復(fù)成默認(rèn)處理

????????//SA_NODEFER在信號(hào)處理程序執(zhí)行期間仍然可以接收信號(hào)

????????sigaction (SIGINT,&act,&oldact) ;//改變信號(hào)的處理模式

????????for (i=1; i<12; i++)

????????{

????????????????printf("signal %d handler is : ",i);

????????????????sigaction (i,NULL,&oldact) ;

????????????????signal_set(&oldact);//如果act為NULL,oldact會(huì)存儲(chǔ)信號(hào)當(dāng)前的行為

????????????????//act不為空,oldact不為空,則oldact會(huì)存儲(chǔ)信號(hào)以前的處理模式

????????}

????????while(1) {

????????????????//等待信號(hào)的到來(lái)

????????}

????????return 0;

}

運(yùn)行結(jié)果:

[root@localhost C]# ./s2

signal 1 handler is : using default hander

signal 2 handler is : 8048437

signal 3 handler is : using default hander

signal 4 handler is : using default hander

signal 5 handler is : using default hander

signal 6 handler is : using default hander

signal 7 handler is : using default hander

signal 8 handler is : using default hander

signal 9 handler is : using default hander

signal 10 handler is : using default hander

signal 11 handler is : using default hander

xxxxx

解釋:

sigaction(i,NULL,&oldact);

signal_set(&oldact);

由于act為NULL,那么oldact保存的是當(dāng)前信號(hào)的行為,當(dāng)前的第二個(gè)信號(hào)的行為是執(zhí)行自定義的處理程序。

當(dāng)按下CTRL+C時(shí)會(huì)執(zhí)行信號(hào)處理程序,輸出xxxxxx,再按一下CTRL+C會(huì)停止,是由于SA_RESETHAND恢復(fù)成默認(rèn)的處理模式,即終止程序。

如果沒(méi)有設(shè)置SA_NODEFER,那么在處理函數(shù)執(zhí)行過(guò)程中按一下CTRL+C將會(huì)被阻塞,那么程序會(huì)停在那里。


示例2: sigqueue向本進(jìn)程發(fā)送數(shù)據(jù)的信號(hào)

void myhandler(int signo, siginfo_t *si, void *ucontext);

int main()? {

????????union sigval val;//定義一個(gè)攜帶數(shù)據(jù)的共用體

????????struct sigaction oldact,act;

????????act.sa_sigaction = myhandler;

????????act.sa_flags = SA_SIGINFO;//表示使用sa_sigaction指示的函數(shù),處理完恢復(fù)默認(rèn),不阻塞處理過(guò)程中到達(dá)下在被處理的信號(hào)

????????//注冊(cè)信號(hào)處理函數(shù)

????????sigaction(SIGUSR1, &act, &oldact);

????????char data[100];

????????int num=0;

????????while( num < 10 )? {

????????????????sleep( 2 );

????????????????printf("等待SIGUSR1信號(hào)的到來(lái)/n");

????????????????sprintf(data, "%d", num++);

????????????????val.sival_ptr=data;

????????????????sigqueue( getpid(), SIGUSR1, val );//向本進(jìn)程發(fā)送一個(gè)信號(hào)

????????????}

}

void myhandler ( int signo, siginfo_t *si, void *ucontext )? {

????????printf("已經(jīng)收到SIGUSR1信號(hào)/n");

????????printf("%s/n",(char*)(si->si_ptr));

}

程序執(zhí)行的結(jié)果是:

等待SIGUSR1信號(hào)的到來(lái)

已經(jīng)收到SIGUSR1信號(hào)

0

等待SIGUSR1信號(hào)的到來(lái)

已經(jīng)收到SIGUSR1信號(hào)

1

等待SIGUSR1信號(hào)的到來(lái)

已經(jīng)收到SIGUSR1信號(hào)

2

等待SIGUSR1信號(hào)的到來(lái)

已經(jīng)收到SIGUSR1信號(hào)

3

等待SIGUSR1信號(hào)的到來(lái)

已經(jīng)收到SIGUSR1信號(hào)

4

等待SIGUSR1信號(hào)的到來(lái)

已經(jīng)收到SIGUSR1信號(hào)

5

等待SIGUSR1信號(hào)的到來(lái)

已經(jīng)收到SIGUSR1信號(hào)

6

等待SIGUSR1信號(hào)的到來(lái)

已經(jīng)收到SIGUSR1信號(hào)

7

等待SIGUSR1信號(hào)的到來(lái)

已經(jīng)收到SIGUSR1信號(hào)

8

等待SIGUSR1信號(hào)的到來(lái)

已經(jīng)收到SIGUSR1信號(hào)

9

解釋:?

本程序用sigqueue不停的向自身發(fā)送信號(hào),并且攜帶數(shù)據(jù),數(shù)據(jù)被放到處理函數(shù)的第二個(gè)參數(shù)siginfo_t結(jié)構(gòu)體中的si_ptr指針,當(dāng)num<10時(shí)不再發(fā)。

一般而言,sigqueue與sigaction配合使用,而kill與signal配合使用。


示例3: 一個(gè)進(jìn)程向另外一個(gè)進(jìn)程發(fā)送信號(hào),并攜帶信息

發(fā)送端:

int main()? {

????????union sigval value;

????????value.sival_int=10;

????????if ( sigqueue(4403, SIGUSR1, value) == -1 )? {? //4403是目標(biāo)進(jìn)程pid

????????????????perror("信號(hào)發(fā)送失敗/n");

????????}

????????sleep(2);

}

接收端:

void myhandler ( int signo, siginfo_t*si, void *ucontext );

int main () {

????????struct sigaction oldact, act;

????????act.sa_sigaction = myhandler;

????????act.sa_flags = SA_SIGINFO | SA_NODEFER;

????????//表示執(zhí)行后恢復(fù),用sa_sigaction指示的處理函數(shù),在執(zhí)行期間仍然可以接收信號(hào)

????????sigaction ( SIGUSR1, &act, &oldact );

????????while ( 1 )? {

????????????????sleep ( 2 );

????????????????printf("等待信號(hào)的到來(lái)/n");

????????}

}

void myhandler ( int signo, siginfo_t *si, void *ucontext ) {

????????printf("the value is %d/n",si->si_int);

}


示例4: sigpending的用法

sigpending (sigset_t *set )將未決信號(hào)放到指定的set信號(hào)集中去,未決信號(hào)包括被阻塞的信號(hào)和信號(hào)到達(dá)時(shí)但還沒(méi)來(lái)得及處理的信號(hào)

void myhandler ( int signo, siginfo_t *si, void *ucontext );

int main()? {

????????struct sigaction oldact, act;

????????sigset_t oldmask, newmask, pendingmask;

????????act.sa_sigaction = myhandler;

????????act.sa_flags = SA_SIGINFO;

????????sigemptyset( &act.sa_mask );? //首先將阻塞集合設(shè)置為空,即不阻塞任何信號(hào)

????????//注冊(cè)信號(hào)處理函數(shù)

????????sigaction(SIGRTMIN + 10, &act ,&oldact);

????????//開(kāi)始阻塞

????????sigemptyset( &newmask );

????????sigaddset( &newmask, SIGRTMIN + 10);

????????printf("SIGRTMIN + 10 blocked/n");

????????sigprocmask( SIG_BLOCK , &newmask ,&oldmask );

????????sleep(20);? //為了發(fā)出信號(hào)

????????printf("now begin to get pending mask/n");

????????if ( sigpending( &pendingmask ) < 0 )? {

????????????????perror("pendingmask error");

????????}

????????if ( sigismember( &pendingmask, SIGRTMIN + 10 ) )? {

????????????????printf("SIGRTMIN+10 is in the pending mask/n");

????????}

????????sigprocmask( SIG_UNBLOCK, &newmask, &oldmask);

? ? ? ? printf("SIGRTMIN+10 unblocked/n");

}

//信號(hào)處理函數(shù)

void myhandler ( int signo, siginfo_t *si, void *ucontext )? {

????????printf("receive signal %d/n",si->si_signo);

}

程序執(zhí)行:

在另一個(gè)shell發(fā)送信號(hào):

kill -44 4579

SIGRTMIN +10 blocked

now begin to get pending mask

SIGRTMIN +10 is in the pending mask

receive signal 44

SIGRTMIN +10 unblocked

可以看到SIGRTMIN由于被阻塞所以處于未決信號(hào)集中。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 信號(hào)的基本概念 信號(hào)被認(rèn)為是一種軟件中斷(區(qū)別于硬件中斷),信號(hào)機(jī)制提供了一種在單進(jìn)程/線程下處理異步事件的方法。...
    小葉大孟閱讀 2,343評(píng)論 0 1
  • 信號(hào)(signal)是一種軟件中斷,它提供了一種處理異步事件的方法,也是進(jìn)程間惟一的異步通信方式。在Linux系統(tǒng)...
    夏大王2019閱讀 1,067評(píng)論 0 1
  • 對(duì)于 Linux來(lái)說(shuō),實(shí)際信號(hào)是軟中斷,許多重要的程序都需要處理信號(hào)。信號(hào),為 Linux 提供了一種處理異步事件...
    故事狗閱讀 86,240評(píng)論 2 63
  • 生理節(jié)奏 所有的生命都受到日--夜這種自然節(jié)律的影響。你的身體受一種被稱作生理節(jié)律的時(shí)間周期所調(diào)節(jié):你的喚醒水平、...
    牧明不是木牧閱讀 498評(píng)論 0 1
  • 1、感賞我的生命中出現(xiàn)的每一個(gè)人,其實(shí)每一個(gè)人都有不易的地方,可是每一個(gè)人都在努力的活著,并努力的活好,自己也是每...
    后來(lái)來(lái)了閱讀 228評(píng)論 0 2

友情鏈接更多精彩內(nèi)容