sigprocmask
在调用sigprocmask后如果有任何未决的、不再阻塞的信号,则在sigprocmask返回前,至少会将其中一个信号递送给该进程。
不能阻塞SIGKILL和SIGSTOP信号。
#include <signal.h>
int sigprocmask( int how, const sigset_t *restrict set, sigset_t *restrict oset );
返回值:若成功则返回0,若出错则返回-1
首先,若oset是非空指针,那么进程的当前信号屏蔽字通过oset返回。
其次,若set是一个非空指针,则参数how指示如何修改当前信号屏蔽字。
信号集操作方法:
#include <signal.h>
int sigemptyset(sigset_t *set);
int sigfillset(sigset_t *set);
int sigaddset(sigset_t *set, int signo);
int sigdelset(sigset_t *set, int signo);
四个函数的返回值:若成功则返回0,若出错则返回-1
int sigismember(const sigset_t *set, int signo);
返回值:若真则返回1,若假则返回0,若出错则返回-1
函数sigemptyset初始化由set指向的信号集,清除其中所有信号。
函数sigfillset初始化由set指向的信号集,使其包括所有信号。
所有应用程序在使用信号集前,要对该信号集调用sigemptyset或sigfillset一次
函数sigaddset将一个信号添加到现有集中,sigdelset则从信号集中删除一个信号。
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
#include <signal.h>
int sigaction( int signo, const struct sigaction *restrict act, struct sigaction *restrict oact);
返回值:若成功则返回0,若出错则返回-1
struct sigaction {
void (*sa_handler)(int); /* addr of signal handler, or SIG_IGN, or SIG_DFL */
sigset_t sa_mask; /* additional signals to block */
int sa_flags; /* signal options */
/* alternate handler */
void (*sa_sigaction)(int, siginfo_t *, void *);
};
这里要注意,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);
}