信号集: 一堆信号的集合,如果想同时设置多个信号的属性,可以先把信号加入到信号集中,再设置信号集的属性。
阻塞掩码: 一个属性,当把某些信号加入到信号集,如果设置了信号集为阻塞状态,那么在阻塞状态下,如果收到信号集中的信号,则暂时不会响应,直到阻塞状态消失了,才会响应!
函数接口:
关于信号集的接口:
sigemptyset, sigfillset, sigaddset, sigdelset, sigismember - POSIX signal set operations.
#include <signal.h>
//清空信号集set
int sigemptyset(sigset_t *set);
//把所有的信号都加入到信号集set中
int sigfillset(sigset_t *set);
//把指定的信号signum加入到信号集set中
int sigaddset(sigset_t *set, int signum);
//把指定的信号signum从信号集中删除
int sigdelset(sigset_t *set, int signum);
返回值:
成功:0
失败:-1
//判断指定的信号signum是否在信号集set中
int sigismember(const sigset_t *set, int signum);
在信号集中: 1
不在信号集中:0
失败:-1
//设置信号集set的属性为how
int sigprocmask(int how, const sigset_t *restrict set,
sigset_t *restrict oset);
信号集的类型: sigset_t
set: 需要处理的信号集的地址
signum : 需要处理的信号值
how:
SIG_BLOCK //设置为阻塞状态
The resulting set shall be the union of the current set and the
signal set pointed to by set.
SIG_UNBLOCK //设置为解除阻塞状态
The resulting set shall be the intersection of the current set
and the complement of the signal set pointed to by set.
oset:一般为NULL
示例:
/** 子进程给父进程发送SIGINT信号,父进程中先把SIGINT信号加入信号集中,
并且设置阻塞状态为5秒,然后解除阻塞 **/
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
#include <stdio.h>
#include <signal.h>
#include <stdlib.h>
void fun(int sig)
{
printf("parent catch sig = %d\n",sig);
}
int main()
{
pid_t x;
x = fork();
if(x > 0)
{
int ret,i;
//1. 捕捉SIGINT信号
signal(SIGINT,fun);
//2. 定义信号集
sigset_t set;
//3. 清空信号集
sigemptyset(&set);
//4. 把SIGINT加入到信号集set中
sigaddset(&set,SIGINT);
//5. 判断信号集set中是否存在SIGINT
ret = sigismember(&set,SIGINT);
if(ret <= 0)
{
printf("sigismember error!\n");
exit(-1);
}
//6. 设置信号集为阻塞状态
sigprocmask(SIG_BLOCK,&set,NULL);
//在10秒内,谁给我发SIGINT这个信号,我都暂时不会响应
for(i=10;i>0;i--)
{
sleep(1);
printf("%d\n",i);
}
//7. 解除阻塞状态
sigprocmask(SIG_UNBLOCK,&set,NULL);
wait(NULL);
exit(0);
}
if(x == 0)
{
//睡1秒,确保让父进程先捕捉信号,并加入到信号集,子进程再发送信号给父进程
sleep(1);
//发送信号给父进程
kill(getppid(),SIGINT);
printf("I send signal to parent!\n");
exit(0);
}
return 0;
}