sigprocmask
在調用sigprocmask後如果有任何未決的、不再阻塞的信號,則在sigprocmask返回前,至少會將其中一個信號遞送給該進程。
不能阻塞SIGKILL和SIGSTOP信號。
#include <signal.h>
int sigprocmask( int how, const sigset_t *restrict set, sigset_t *restrict oset );
返回值:若成功則返回0,若出錯則返回-1
sigprocmask是僅爲單線程的進程定義的。
進程屏蔽信號集
#include "apue.h"
static void sig_quit();
int main()
{
sigset_t newmask,oldmask,pendingmask;
if(signal(SIGQUIT,sig_quit)<0)
printf("can't catch SIGQUIT");
sigemptyset(&newmask);
sigaddset(&newmask,SIGQUIT);
if(sigprocmask(SIG_BLOCK,&newmask,&oldmask)<0)
printf("SIG_BLOCK error");
sleep(8);
if(sigpending(&pendingmask)<0)
printf("pendingmask error");
if(sigismember(&pendingmask,SIGQUIT))
printf("\n SIGQUIT pengding");
if(sigprocmask(SIG_SETMASK,&oldmask,NULL)<0)
printf("SIG_SETMASK error");
if(sigpending(&pendingmask)<0)
printf("pendingmask error");
if(sigismember(&pendingmask,SIGQUIT))
{
printf("\n SIGQUIT pengding");
}
else
{
printf("\n SIGQUIT is not pengded");
}
}
static void sig_quit(int signo)
{
printf("caught SIGQUIT\n");
if(signal(SIGQUIT,SIG_DFL)==SIG_ERR)
printf("cat't reset SIGQUIT");
}
sigaction
參考鏈接添加鏈接描述
這裏要注意,SA_NODEFER 表示信號處理函數可以重複進入,原調用該信號處理函數後,操作系統會將該信號加入mask裏,阻塞表裏,進入信號後,會被阻塞。當該函數執行完畢後,會再次處理該函數!但是如果SA_RESETHAND,那麼該信號處理函數將會設置缺省值SIG_DFL!!!如果設置sa_flags = 0 ,那麼原調用該信號處理函數後,會阻塞,不能重複進入,必須等函數執行完畢!!!
- sa_handler此參數和signal()的參數handler相同,代表新的信號處理函數
- sa_mask 用來設置在處理該信號時暫時將sa_mask 指定的信號集擱置
- sa_flags 用來設置信號處理的其他相關操作,下列的數值可用。
- SA_RESETHAND:當調用信號處理函數時,將信號的處理函數重置爲缺省值SIG_DFL
- SA_RESTART:如果信號中斷了進程的某個系統調用,則系統自動啓動該系統調用
- SA_NODEFER :一般情況下, 當信號處理函數運行時,內核將阻塞該給定信號。但是如果設置了 SA_NODEFER標記, 那麼在該信號處理函數運行時,內核將不會阻塞該信號
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <signal.h>
void show_handler(int sig)
{
printf("I got signal %d\n", sig);
int i;
for(i = 0; i < 5; i++)
{
printf("i = %d\n", i);
sleep(1);
}
}
int main(void)
{
int i = 0;
struct sigaction act, oldact;
act.sa_handler = show_handler;
sigaddset(&act.sa_mask, SIGQUIT); //見注(1)
act.sa_flags = SA_RESETHAND | SA_NODEFER; //見注(2)
//act.sa_flags = 0; //見注(3)
sigaction(SIGINT, &act, &oldact); //sigaction是執行信號處理函數的時候屏蔽!!!!
pr_mask("hello world!!!!!!"); //與int sigprocmask( int how, const sigset_t *restrict set, sigset_t *restrict oset );
// 不一樣!!!!!!sigprocmask是屏蔽但線程的進程
while(1)
{
sleep(1);
printf("sleeping %d\n", i);
i++;
}
}
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <signal.h>
void handler();
int main()
{ //sigaction都是設置與捕捉信號有關的處理
struct sigaction act,old;
sigemptyset(&act.sa_mask);
sigaddset(&act.sa_mask,SIGQUIT);
act.sa_flags = 0;
act.sa_handler = handler;
//sigaction(SIGINT,&act,&old); //這裏是在捕捉信號時,阻塞SIGQUIT
sigprocmask(SIG_SETMASK,&act.sa_mask,NULL); //主進程阻塞SIGQUIT信號!!
//signal(SIGINT,handler);
while(1)
{
int d = 0;
d++;
printf("value d is : %d\n ",d);
sleep(1);
}
}
void handler(int signum)
{
int i=0;
for(;i<5;i++){
printf("value i is : %d\n ",i);
sleep(1);
}
}
重寫signal
#include "apue.h"
Sigfunc* signal(int signo, Sigfunc* func)
{
struct sigaction act, old;
sigemptyset(&act.sa_mask);
act.sa_handler = func;
act.flags = 0;
if(signo == SIGALARM)
{
#ifdef SA_INTERUPT
act.sa_flags |= SA_INTERUPT; //被阻止的系統調用不會重啓
#endif
}
else{
#ifdef SA_RESTART
act.sa_flags |= SA_RESTART; //被阻止的系統調用會重啓
#endif
}
if (sigaction(,&act,&old)<0)
return(SIG_ERR);
return(old.sa_handler);
}