信号集的函数:
类型:sigset_t 类型
/****************************
*功能:把一个信号集的内容清空
*参数:sigset_t *set:是一个信号集,sigset_t的类型一定是可以容纳所有的信号的个数
*返回值:成功返回0,失败返回-1
* ************************/
int sigemptyset(sigset_t *set);
/****************************
*功能:把一个信号集的内容填满,包含所有的信号
*参数:sigset_t *set:是一个信号集,sigset_t的类型一定是可以容纳所有的信号的个数
*返回值:成功返回0,失败返回-1
* ************************/
int sigfillset(sigset_t *set);
/****************************
*功能:把一个信号添加到信号集中
*参数:sigset_t *set:是一个信号集,sigset_t的类型一定是可以容纳所有的信号的个数
*返回值:成功返回0,失败返回-1
* ************************/
int sigaddset(sigset_t *set, int signum);
/****************************
*功能:把一个信号从信号集中删除
*参数:sigset_t *set:是一个信号集,sigset_t的类型一定是可以容纳所有的信号的个数
*返回值:成功返回0,失败返回-1
* ************************/
int sigdelset(sigset_t *set, int signum);
/****************************
*功能:判断是否是信号是否在指定集合中
*参数:sigset_t *set:是一个信号集,sigset_t的类型一定是可以容纳所有的信号的个数
*返回值:成功返回0,失败返回-1
* ************************/
int sigismember(const sigset_t *set, int signum);
sigprocmask函数:
用来读取或者更改进程的信号屏蔽集。
int sigprocmask(int how, const sigset_t *set, sigset_t *oldset);
如果 set 为空 oldset 不为空, 则会将进程原来的信号屏蔽集传出;
如果 set 不为空,oldset 为空, 则会根据 how 参数的指示修改进程的信号屏蔽集;
如果两个指针都不为空, 则先备份原来的信号屏蔽字到 oldset, 然后根据 how参数修改。
how参数有如下函数
值 | 含义 |
SIG_BLOCK | 屏蔽信号,添加的信号屏蔽字不覆盖之前的,这是一个并集的关系 |
SIG_UNBLOCK | 希望解除BLOCK的信号集合。 |
SIG_SETMASK | 该进程的信号屏蔽是set指向的值。 |
注意到这里后两个参数,set
用以设置新的信号屏蔽字,oldset
返回当前信号屏蔽字。
如果不进行设置,仅仅只是想得到当前的信号屏蔽字,那么前两个参数也就没有意义了。
sigprocmask(0,NULL,&sigset);
sigpending函数:
int sigpending(sigset_t *set);
函数说明:sigpending()会将被阻塞的信号集合由参数set 指针返回.返回值:执行成功则返回 0, 如果有错误则返回-1.
简单程序实例:
程序运行时,每秒打印一此未决状态信号集,初始全为0,当输出ctrl-c时, 由于我们阻塞了SIGINT信号, 会使该信号处于未决状态。
// 打印信号集
void
printsigset(const sigset_t *set)
{
int i = 0;
for(; i<6; ++i)
{
if(sigismember(set, i) == 1)
printf("signal[%d] = 阻塞\n", i);
else
printf("signal[%d] = 未阻塞\n", i);
}
printf("\n");
}
int
main()
{
sigset_t s;
sigemptyset(&s); // 初始化
sigaddset(&s, SIGINT); //添加SIGINT,
sigprocmask(SIG_BLOCK, &s, NULL ); //把当前信号集 s 变为 屏蔽信号集,
//这个信号集里的信号会被阻塞
while(1)
{
sigpending(&s);
printsigset(&s);
sleep(3);
}
return 0;
}
结果:
该程序的运行结果如下, 可以看见, 在信号处于阻塞状态时, 所发出的信号对进程不起
作用, 并且该信号进入待处理状态。 读者按任意键, 并且信号脱离了阻塞状态后, 用户发出
的信号才能正常运行。 这里 SIGINT 已按照用户自定义的函数运行, 请读者注意阻塞状态下
SIGINT 的处理和非阻塞状态下 SIGINT 的处理有何不同。
/* 自定义的信号处理函数 */
void my_func(int signum)
{
printf("If you want to quit,please try SIGQUIT\n");
}
int main()
{
sigset_t set;
sigset_t pendset;
struct sigaction action1;
struct sigaction action2;
/* 初始化信号集为空 */
if (sigemptyset(&set) < 0)
{
perror("sigemptyset");
exit(1);
} /* 将相应的信号加入信号集 */
if (sigaddset(&set, SIGQUIT) < 0)
{
perror("sigaddset");
exit(1);
}
if (sigaddset(&set, SIGINT) < 0)
{
perror("sigaddset");
exit(1);
}
if (sigismember(&set, SIGINT))
{
sigemptyset(&action1.sa_mask);
action1.sa_handler = my_func;
action1.sa_flags = 0;
sigaction(SIGINT, &action1, NULL); //注册函数
}
if (sigismember(&set, SIGQUIT))
{
sigemptyset(&action2.sa_mask);
action2.sa_handler = SIG_DFL;
action2.sa_flags = 0;
sigaction(SIGQUIT, &action2,NULL); //注册函数
}
/* 设置信号集屏蔽字, 此时 set 中的信号不会被传递给进程, 暂时进入待处理状态 */
if (sigprocmask(SIG_BLOCK, &set, NULL) < 0)
{
perror("sigprocmask");
exit(1);
}else
{
printf("Signal set was blocked, Press any key!");
//getchar(); /*按下键后就会执行信号函数*/
}
/* 在信号屏蔽字中删除 set 中的信号 */
if (sigprocmask(SIG_UNBLOCK, &set, NULL) < 0)
{
perror("sigprocmask");
exit(1);
}else
{
printf("Signal set is in unblock state\n");
}
while(1);
exit(0);
}
结果:
# ./a.out
Signal set was blocked, Press any key!^C^C^C //按下多次ctr+c,但只处理一次
If you want to quit,please try SIGQUIT
Signal set is in unblock state /* 从信号屏蔽字中删除 set 中的信号 */
^CIf you want to quit,please try SIGQUIT /* 非阻塞状态下 SIGINT 的处理 */
^CIf you want to quit,please try SIGQUIT