我有这个代码,我使用sigaddset和sigaction。但是,如果我评论segaddset,结果是相同的
struct sigaction act;
act.sa_handler = process_alarm;
act.sa_flags = 0;
sigemptyset(&act.sa_mask);
//sigaddset(&act.sa_mask, SIGINT);
sigaction(SIGALRM, &act, NULL);
for(;;)
{
alarm(3);
pause();
}
为什么我需要使用它?
答案 0 :(得分:13)
你在这做两件事:
填充sigset_t
。 sigset_t只是信号值的集合,用于各种系统调用。你可以:
设置信号处理程序的信号掩码。当您通过调用sigaction()设置信号处理程序时,可以通过操纵sigset_t sa_mask
的{{1}}成员来实现此目的。
信号处理程序的信号掩码意味着当信号处理程序正在执行时,掩码中的信号将被阻止 - 即只要它们被阻塞,这些信号就不会被处理。信号处理程序完成后,信号输入将被解除阻塞。 被阻止的信号不会丢失",当特定信号再次被阻塞时,它将被处理。
struct sigaction
表示在sigaddset(&act.sa_mask, SIGINT);
处理程序的代码运行时不会发生SIGINT信号。
另一方面,如果您注释掉SIGALRM
,则只剩下使用sigaddset(&act.sa_mask, SIGINT);
创建的空信号列表。因此,在SIGALRM处理程序函数运行时发生的任何信号都可能抢占该处理程序并执行该另一个信号的信号处理程序。
对于SIGINT,您通常不会注意到与手动测试有任何区别 - 当您的SIGALRM处理程序正在运行时,您不可能设法完全按CTRL-C,并且您的SIGALRM处理程序可能运行得足够快如果SIGINT稍有延迟,我们不会注意到。
答案 1 :(得分:6)
信号集通过sigset_t
类型进行操作。有几种操作可用于信号集:
sigemptyset
创建一个空集S,S =∅sigaddset
,S =S∪{s} sigdelset
,S = S \ {s} sigfillset
创建所有可能信号的集合。sigismember
,s∈S?这样的一组用于不同的地方:设置一个新的过程信号掩码,在信号处理过程中阻塞设置,请求待定信号集等等。
如果您想捕获不同的信号,可能看起来某些捕捉功能不能被其他信号中断,因此您可以在传送给定信号期间添加一组要阻止的信号。实际上,您决定(在取消注释时)在SIGALRM传递期间阻止SIGINT。所以你只能通过在执行处理程序期间发送SIGINT来观察这个;这很难实现。
一个重要的例子吗?
假设SIGUSR1的处理程序修改给定的数据结构,并且SIGUSR2的处理程序使用相同的数据结构。让两个处理程序不同时非常重要,一个可以在另一个之后运行,但是你可能不想在另一个交付期间被一个人打断。您的代码是自并发,即使只有一个线程,信号也可以引导您并发。
答案 2 :(得分:0)
sigaddset用于将相应的信号掩码添加到该sigset_t变量。
在sigaction中,它不是必需的。当您使用sigprocmask来阻止我们在该变量中提到的信号时,您可以使用它。