信号集:
表示多个信号的数据类型,由128个二进制位组成,每个二进制位表示一个信号。
与其相关的函数有:
int sigemptyset(sigset_t *set);
功能:清空信号集
int sigfillset(sigset_t *set);
功能:填满信号信
int sigaddset(sigset_t *set, int signum);
功能:向信号集中添加信号
int sigdelset(sigset_t *set, int signum);
功能:从信号集中删除信号
前四个返回值:若成功返回0;若出错,返回-1 。
int sigismember(const sigset_t *set, int signum);
功能:测试一个信号集中是否有某个信号
返回值:若真,返回1;若假,返回0 。
信号屏蔽:
每个进程都有一个信号掩码(signal mask),也叫信号屏蔽码,它是一个信号集,其中包括了需要屏蔽的信号。
为什么需要屏蔽信号呢?当进程执行一些敏感操作时不希望被打扰,此时需要屏蔽信号。
注意:
1.屏蔽信号的目的不是为了不接收信号,而是延时接收,当处理完要做的事情后,应该把屏蔽的信号还原。
2.当信号屏蔽时发生的信号会记录一次,这个信号设置为未决状态,当信号屏蔽结束后,会再发送一次。
3.不可靠信号在信号屏蔽期间无论信号发生多少次,信号解除屏蔽后,只发送一次。
4.可靠信号在信号屏蔽期间发生的信号会排队记录,在信号解除屏蔽后逐个处理。
5.在执行处理函数时,会默认把当前处理的信号屏蔽掉,执行完成后再恢复
信号屏蔽函数:(可以检测,更改进程的信号屏蔽字)
int sigprocmask(int how, const sigset_t *set, sigset_t *oldset);
头文件:#include <signal.h>
功能:设置进程的信号掩码(信号屏蔽码)
how:修改信号掩码的方式
SIG_UNBLOCK:从信号掩码中删除信号
SIG_BLOCK:向信号掩码中添加信号
SIG_SETMASK:用新的信号集替换旧的信号掩码
set:新添加、删除、替换的信号集,主要是由how决定,当set为空时,则不改变该进程的信号屏蔽字,how的值也将毫无意义。
oldset:获取旧的信号掩码。
下面演示一个屏蔽信号Ctrl+c 5秒的例子
#include <stdio.h>
#include <signal.h>
#include <unistd.h>
void updata(void)//sleep 5s 每秒都打印 以便观察
{
for (int i = 0; i < 5; ++i)
{
printf("updata %d data\n",i);
sleep(1);
}
}
void sigint(int signum)//Ctrl+c signal handler
{
printf("Receive %d data \n",signum);
}
int main(int argc, char const *argv[])
{
signal(SIGINT,sigint);
sigset_t set,oldset;//初始化信号集
sigemptyset(&set);
printf("add %s\n",sigaddset(&set,SIGINT)?"fail":"success");//在屏蔽集中添加SIGINT
//将屏蔽集指向set所设的信号集
printf("set mask %s\n",sigprocmask(SIG_SETMASK,&set,&oldset)?"fail":"success");
updata();
//屏蔽集指向oldset,即默认的屏蔽设置
printf("set mask %s\n",sigprocmask(SIG_SETMASK,&oldset,NULL)?"fail":"success");
pause();
return 0;
}
编译结果:
可以看到,在屏蔽的5s期间ctrl+c的命令是被屏蔽的
当屏蔽结束时,可以看到只处理了一次ctrl+c,当我们屏蔽后再一次输入ctrl c 进程才结束。