信号集
定义:信号集表示一组信号的来(1)或者没有来(0)。
数据类型:sigset_t
//sigset_t结构大概长这个样子
typedef struct{
unsigned long sig[2];
}sigset_t;
信号相关函数
(1)sigemptyset 把信号集中的所有信号都清零
(2) sigfillset 把信号集中的所有信号都设置为1
(3)信号集中支持60多个信号,可以向信号集中增加(信号标志设置为1)或删除(信号标志设置为0)特定的信号,用 sigaddset 和 sigdelset 就可以做到。sigaddset 用于将某个信号位设置为1,sigdelset用于将某个信号位设置为 0。
(4)sigprocmask、sigismember
sigprocmask 用于设置进程所对应的信号集(进程有默认的信号集)。
sigismember 函数用于检测信号集的特定信号是否被置位。
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
//信号处理函数
void sig_quit(int signo)
{
printf("收到了SIGQUIT信号!\n");
if (signal(SIGQUIT, SIG_DFL) == SIG_ERR) {
printf("无法为SIGQUIT信号设置默认处理!\n");
exit(1);
}
}
int main(int argc,char* const *argv)
{
//定义新的信号集和原有的信号集
sigset_t newmask, oldmask, pendmask;
//注册信号对应的信号处理函数
if (signal(SIGQUIT, sig_quit) == SIG_ERR)
{
printf("无法捕捉 SIGUSR1 信号!\n");
//退出程序,参数是错误代码,0表示正常退出,非0表示错误,但具体什么错误,没有特定规定
exit(1);
}
//newmask 信号集中所有信号都清零(表示这些信号都没有来)
sigemptyset(&newmask);
//设置newmask信号集中的SIGQUIT信号为1,再来SIGQUIT信号时进程就收不到
sigaddset(&newmask, SIGQUIT);
//设置该进程所对应的信号集
if (sigprocmask(SIG_BLOCK, &newmask, &oldmask) < 0)
///第一个参数用了SIG_BLOCK, 表明设置进程新的信号屏蔽字为当前信号屏蔽字和第2个参数指向的信号集的并集。一个“进程”的当前信号屏蔽字,
///开始全部为0,相当于把当前“进程”的信号屏蔽字设置成newmask(屏蔽了SIGQUIT)。第3个参数不为空,则进程老的信号集会保存到第3个参数里,
///以备后续恢复用
{
printf("sigprocmask(SIG_BLOCK)失败!\n");
exit(1);
}
printf("我要开始休息10s了--------begin-----此时我无法接收SIGOUT信号!\n");
sleep(10);
printf("我已经休息10s了----------end---!\n");
if (sigismember(&newmask, SIGQUIT)) {
printf("SIGQUIT信号被屏蔽了!\n");
}
else {
printf("SIGQUIT信号没有被屏蔽!\n");
}
//
if (sigismember(&newmask, SIGHUP)) {
printf("SIGHUP信号被屏蔽了!\n");
}
else {
printf("SIGHUP信号没有被屏蔽!\n");
}
//现在取消对SIGQUIT信号的屏蔽----把信号集还原回去
if (sigprocmask(SIG_SETMASK, &oldmask, NULL) < 0){
printf("sigprocmask(SIG_SETMASK)失败!\n");
exit(1);
}
printf("sigprocmask(SIG_SETMASK)成功!\n");
if (sigismember(&oldmask, SIGQUIT)) {
printf("SIGQUIT信号被屏蔽了!\n");
}
else {
printf("SIGQUIT信号没有被屏蔽, 您可以发送SIGQUIT信号了,我要sleep10s!\n");
int mysl = sleep(10);
if (mysl > 0) {
printf("sleep()还没有睡够,剩余%d\n", mysl);
}
}
printf("再见了!\n");
return 0;
}
重要结论:
信号有等待机制,但无法允许多个相同的信号排队等待(只留1个,其余的相同信号被忽略)