2011-03-13 79 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"); 
} 
}