? 每個進程都有一個用來描述哪些信號傳送來將被阻塞的阻塞的信號集,如果某種信號在某個進程的阻塞信號集中,則傳送到該進程的此種信號將會被阻塞。信號阻塞操作主要有以下三個函數(shù):
??
?? #include<signal.h>
?? int sigprocmask(int how, const sigset_t *set, sigset_t *oldset);
?? int sigpending(sigset_t *set);
?? int sigsuspend(const sigset_t *mask);
??
?? sigprocmask系統(tǒng)調(diào)用用于改變當(dāng)前阻塞信號集,它具體的功能主要取決于第一個參數(shù)how。how的取值如下:
????????? -----------------------------------------------------------------------------------------------------
?????????? 參數(shù)how?????? |?????????????????? ?? 動作
????????? ------------------------------------------------------------------------------------------------------
???????????? SIG_BLOCK???? |???? 將set指向的信號集中的信號添加到當(dāng)前阻塞信號集中
????????? ------------------------------------------------------------------------------------------------------
???????? SIG_UNBLOCK??? |???? 從當(dāng)前阻塞信號集中移除set指向的信號集中的信號,
??????????????????? ?? ?? |???? 移除一個阻塞信號集中不存在的信號那也是合法的
????????? ------------------------------------------------------------------------------------------------------
????????? SIG_SETMASK??? |???? 指定set所指向的信號集為當(dāng)前阻塞信號集
???????? --------------------------------------------------------------------------------------------------------
???? 如果sigprocmask的第三個參數(shù)oldset非空,則oldset保存舊的信號阻塞集。
????
??? sigpending(…)獲得當(dāng)前已傳送到進程,卻被阻塞的所有信號,在set指向的信號集中保存未決(阻塞)的信號。
??? sigsuspend(const sigset_t
*mask),
在接收到某個信號之前,臨時用mask替換進程的信號掩碼,并掛起進程,直到收到信號為止。sigsuspend返回后,即系統(tǒng)在接受到信
號后,進程將恢復(fù)調(diào)用前的信號掩碼,調(diào)用信號處理函數(shù)完畢后進程將繼續(xù)執(zhí)行。始終返回-1,并將errno設(shè)置為EINTR。
???
??? 下面這個小程序測試了信號的阻塞以及信號集操作:
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <unistd.h>
#define BLOCK_SIG??? SIGRTMIN+10
/*信號處理函數(shù)*/
static void sig_handler(int signum,struct siginfo *sig_info,void *unused)
{
??? printf("\n<! receive signal %d !>\n",signum);
??? printf("-----------------< Signal information >--------------------\n");
??? printf("\tsi_signo :\t%d\n",sig_info->si_signo);//信號值
??? printf("\tsi_errno :\t%d\n",sig_info->si_errno);//error值
??? printf("\tsi_code :\t%d\n",sig_info->si_code); //信號產(chǎn)生的原因
??? printf("\tsi_int?? :\t%d\n",sig_info->si_int); //4 bytes 整型???
???
}
int main(int argc,char**argv)
{
??? sigset_t new_mask,old_mask,pending_mask;
??? struct sigaction act;
???
??? printf("Block precess PID : %d\n",getpid());
??? /*
??? *設(shè)置struct sigaction結(jié)構(gòu)
??? */
??? sigemptyset(&act.sa_mask);
??? act.sa_flags=SA_SIGINFO;
??? act.sa_sigaction=(void *)sig_handler;
??????? /*
??? *安裝信號
??? */
??? if(sigaction(BLOCK_SIG,&act,NULL))
??? ??? printf("install siganl SIGRTMIN+10 error!\n");
??????? /*
??? *設(shè)置新的屏蔽信號集,阻塞 SIGRTMIN+10 信號!
??? */
??? sigemptyset(&new_mask);
??? sigaddset(&new_mask,BLOCK_SIG);
??? if(sigprocmask(SIG_BLOCK,&new_mask,&old_mask))
??? ??? printf("block signal SIGRTMIN+10 error!\n");
??? sleep(30);//等待信號SIGRTMIN+10喚醒,但因為上面設(shè)置了此信號阻塞,因此此處不能從睡眠中喚醒進程
??? printf("\nNow begin to get pending mask and unblock SIGRTMIN_10\n");
??? sigpending(&pending_mask);?? //獲得當(dāng)前已傳送到進程,卻被阻塞的所有信號
??? if(sigismember(&pending_mask,BLOCK_SIG))
??? ??? printf("\nsignal SIGRTMIN+10 is pending!\n");
??? /*
???? *恢復(fù)原來的信號屏蔽集,此前被阻塞的信號觸發(fā)
???? */
??? sigprocmask(SIG_SETMASK,&old_mask,NULL);
??? printf("\nsignal unblocked!\n");
??? /*
??? *進程進入睡眠,直到有信號喚醒進程,或時間到!
??? */
??? sleep(30);
???
??? exit(0);
}
???
???? 配合上篇中介紹的信號發(fā)送小程序,你可以測試一下程序的執(zhí)行結(jié)果!