信號處理函數(shù)

信號處理函數(shù)


sigaction的用法

int sigaction (

????????int signo,

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

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

);

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

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

第二個參數(shù),第三個參數(shù)是對信號進行細粒度的控制。

如果*act不為空,*oldact不為空,那么oldact將會存儲信號以前的行為。

如果act為空,*oldact不為空,那么oldact將會存儲信號現(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是一個函數(shù)指針,主要是表示接收到信號時所要采取的行動。此字段的值可以是SIG_DFL,SIG_IGN.分別代表默認操作與內核將忽略進程的信號。這個函數(shù)只傳遞一個參數(shù)那就是信號代碼。

當SA_SIGINFO被設定在sa_flags中,那么則會使用sa_sigaction來指示信號處理函數(shù),而非sa_handler.

sa_mask設置了掩碼集,在程序執(zhí)行期間會阻擋掩碼集中的信號。

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

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

sa_restorer已經被廢棄。

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

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

第一個參數(shù): 信號編號

第二個參數(shù):指向一個siginfo_t結構。

第三個參數(shù)是一個ucontext_t結構。

其中siginfo_t結構體中包含了大量的信號攜帶信息,可以看出,這個函數(shù)比sa_handler要強大,因為前者只能傳遞一個信號代碼,而后者可以傳遞siginfo_t信息。

typedef struct siginfo_t {

????????int si_signo;//信號編號

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

????????int si_code;//說明進程如何接收信號以及從何處收到

????????pid_t si_pid;//適用于SIGCHLD,代表被終止進程的PID

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

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

????????clock_t si_utime;//適用于SIGCHLD,代表被終止進程所消耗的用戶時間

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

????????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,也是一個進程向另外一個進程發(fā)送信號的。

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

第一個參數(shù)指定目標進程的pid.

第二個參數(shù)是一個信號代碼。

第三個參數(shù)是一個共用體,每次只能使用一個,用來進程發(fā)送信號傳遞的數(shù)據。

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

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

sigpending的用法

sigpending(sigset_t set);

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

即未決信號集,未決信號集不僅包括被阻塞的信號,也可能包括已經到達但沒有被處理的信號。

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

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

????????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 在處理完信號之后,將信號恢復成默認處理

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

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

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

????????{

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

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

????????????????signal_set(&oldact);//如果act為NULL,oldact會存儲信號當前的行為

????????????????//act不為空,oldact不為空,則oldact會存儲信號以前的處理模式

????????}

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

????????????????//等待信號的到來

????????}

????????return 0;

}

運行結果:

[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保存的是當前信號的行為,當前的第二個信號的行為是執(zhí)行自定義的處理程序。

當按下CTRL+C時會執(zhí)行信號處理程序,輸出xxxxxx,再按一下CTRL+C會停止,是由于SA_RESETHAND恢復成默認的處理模式,即終止程序。

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


示例2: sigqueue向本進程發(fā)送數(shù)據的信號

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

int main()? {

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

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

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

????????act.sa_flags = SA_SIGINFO;//表示使用sa_sigaction指示的函數(shù),處理完恢復默認,不阻塞處理過程中到達下在被處理的信號

????????//注冊信號處理函數(shù)

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

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

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

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

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

????????????????printf("等待SIGUSR1信號的到來/n");

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

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

????????????????sigqueue( getpid(), SIGUSR1, val );//向本進程發(fā)送一個信號

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

}

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

????????printf("已經收到SIGUSR1信號/n");

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

}

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

等待SIGUSR1信號的到來

已經收到SIGUSR1信號

0

等待SIGUSR1信號的到來

已經收到SIGUSR1信號

1

等待SIGUSR1信號的到來

已經收到SIGUSR1信號

2

等待SIGUSR1信號的到來

已經收到SIGUSR1信號

3

等待SIGUSR1信號的到來

已經收到SIGUSR1信號

4

等待SIGUSR1信號的到來

已經收到SIGUSR1信號

5

等待SIGUSR1信號的到來

已經收到SIGUSR1信號

6

等待SIGUSR1信號的到來

已經收到SIGUSR1信號

7

等待SIGUSR1信號的到來

已經收到SIGUSR1信號

8

等待SIGUSR1信號的到來

已經收到SIGUSR1信號

9

解釋:?

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

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


示例3: 一個進程向另外一個進程發(fā)送信號,并攜帶信息

發(fā)送端:

int main()? {

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

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

????????if ( sigqueue(4403, SIGUSR1, value) == -1 )? {? //4403是目標進程pid

????????????????perror("信號發(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í)行后恢復,用sa_sigaction指示的處理函數(shù),在執(zhí)行期間仍然可以接收信號

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

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

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

????????????????printf("等待信號的到來/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 )將未決信號放到指定的set信號集中去,未決信號包括被阻塞的信號和信號到達時但還沒來得及處理的信號

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ù)

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

????????//開始阻塞

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

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

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

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

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

????????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");

}

//信號處理函數(shù)

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

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

}

程序執(zhí)行:

在另一個shell發(fā)送信號:

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由于被阻塞所以處于未決信號集中。

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

相關閱讀更多精彩內容

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

友情鏈接更多精彩內容