2011-03-13 31 views
5

我写了一小段代码。此代码首先阻止{SIGSEGV},然后将SIGRTMIN添加到同一组。所以,我最后的信号集是{SIGSEGV,SIGRTMIN}。因此,如果我使用SIG_UNBLOCK,按照我的理解,首先SIGRTMIN应该被解除阻塞,然后再次如果我调用SIG_UNBLOCK,SIGSEGV应该被解除阻塞。即,1){SIGSEGV,SIGRTMIN} 2)SIG_UNBLOCK =解锁SIGRTMIN,3)再次调用SIG_UNBLOCK =解锁SIGSEGV。 我只给SIGRTMIN一个进程,因此我的第二个unblock应该用SIGRTMIN停止进程。但事实并非如此。请帮忙。 N.B:请不要给出关于sigprocmask()上其他问题的答案的链接,我已经看到他们,他们也没有澄清我的问题。sigprocmask()在UNIX中阻止信号

enter code here 
#include <signal.h> 
#include <unistd.h> 
#include <stdio.h> 

int main() 
{ 
sigset_t old_set,new_set; 
sigemptyset(&old_set); 
sigemptyset(&new_set); 

if(sigaddset(&old_set,SIGSEGV)==0) 
{ 
    printf("sigaddset successfully added for SIGSEGV\n"); 
} 
sigprocmask(SIG_BLOCK,&old_set,NULL); // SIGSEGV signal is masked 
kill(0,SIGSEGV); 


//***************************************************************** 

if(sigaddset(&new_set,SIGRTMIN)==0) 
{ 
    printf("sigaddset successfully added for SIGRTMIN\n"); 
} 
    sigprocmask(SIG_BLOCK,&new_set,&old_set); // SIGRTMIN signal is masked 
kill(0,SIGSEGV); 

//****************** Unblock one signal at a time ****************** 

sigprocmask(SIG_UNBLOCK,&new_set,&old_set); // SIGRTMIN signal is unmasked 
sigprocmask(SIG_UNBLOCK,&new_set,&old_set); // SIGSEGV signal is unmasked 

}

Output: 
[[email protected] signals]# ./a.out 
    sigaddset successfully added for SIGSEGV 
    sigaddset successfully added for SIGRTMIN 
    (Note:SIGSEGV is not received even after sigprocmask(SIG_UNBLOCK,&new_set,&old_set); a second time) 

回答

11

你的前提是错误的。通过sigprocmask的单个呼叫,整个组被阻止并解除阻塞。另外,通常你会创建一个包含你想要阻塞的每个信号的集合,然后你会尝试用sigprocmask(SIG_BLOCK, pointer_to_sigset);来阻止它们。

虽然您的代码并未真正解锁SIGSEGV。以下是我在没有错误处理的情况下编写的内容,因为它会使片段不必要地长。检查每一个功能 因为虽然,可能出现的错误的列表是通过手册页提供错误:

/* ... */ 
sigset_t signal_set; /* We don't need oldset in this program. You can add it, 
         but it's best to use different sigsets for the second 
         and third argument of sigprocmask. */ 
sigemptyset(&signal_set); 

sigaddset(&signal_set, SIGSEGV); 
sigaddset(&signal_set, SIGRTMIN); 

/* now signal_set == {SIGSEGV, SIGRTMIN} */ 

sigprocmask(SIG_BLOCK, &signal_set, NULL): /* As i said, we don't bother with the 
               oldset argument. */ 

kill(0,SIGSEGV); 
kill(0,SIGSEGV); /* SIGSEGV is not a realtime signal, so we can send it twice, but 
        it will be recieved just once */ 

sigprocmask(SIG_UNBLOCK, &signal_set, NULL); /* Again, don't bother with oldset */ 

/* SIGSEGV will be received here */ 

当然,你可能想分裂阻断信号转换成上单独设置两个操作。该机制的工作原理是这样的:有一组被阻塞的信号,如果你提供了一个oldset参数,它将取代oldset。您可以使用SIG_BLOCK添加到该集合,从SIG_UNBLOCK中删除该集合,并使用sigprocmask函数的SIG_SETMASK参数将整个集合更改为您喜欢的集合。

+0

@ kubi:那么为什么我没有收到SIGSEGV? – kingsmasher1 2011-03-13 10:57:56

+0

@ kubi:不,我不认为整套游戏一次就能畅通无阻。检查链接:http://stackoverflow.com/questions/25261/help-with-sigprocmask。此外,sigprocmask()本身不会阻塞或解除阻塞,它是使阻塞,解除阻塞或屏蔽的参数或第一个参数。所以,在指出我错误之前请先思考。 – kingsmasher1 2011-03-13 10:59:49

+0

@ kingsmasher1:你如何处理'SIGSEGV'?你能粘贴一个信号处理程序代码片段吗?信号是否被正确发送?检查“sigprocmask”和“kill”的错误代码。 – kubi 2011-03-13 11:05:20

0

正如kubi指出的那样:这里是修改的代码,问题是,我搞砸了old_set和new_set。 SIGSEGV被添加到old_set中,但未被解除阻塞,因此我没有收到Segmentation故障(SIGSEGV信号)。 感谢kubi。

enter code here 
#include <signal.h> 
#include <unistd.h> 
#include <stdio.h> 

int main() 
{ 
sigset_t old_set,new_set; 
sigemptyset(&old_set); 
sigemptyset(&new_set); 

if(sigaddset(&old_set,SIGSEGV)==0) 
{ 
    printf("sigaddset successfully added for SIGSEGV\n"); 
} 
sigprocmask(SIG_BLOCK,&new_set,&old_set); // SIGSEGV signal is masked 
kill(0,SIGSEGV); 


//***************************************************************** 

if(sigaddset(&new_set,SIGRTMIN)==0) 
{ 
    printf("sigaddset successfully added for SIGRTMIN\n"); 
} 
if(sigprocmask(SIG_BLOCK,&new_set,&old_set)==-1) // SIGRTMIN signal is masked 
{ 
    perror("sigprocmask"); 
} 
kill(0,SIGSEGV); 


//****************** Unblock all signals ****************** 

if(sigprocmask(SIG_UNBLOCK,&new_set,&old_set)==-1) // SIGRTMIN signal is unmasked 
{ 
    perror("sigprocmask"); 
} 
}