2012-10-29 69 views
5

有沒有辦法阻止某些信號並解除同一組中的其他信號? 我只是似乎沒有得到我的頭!posix線程阻塞信號並解除阻塞

一個例子

sigset_t set; 
sigemptyset(&set); 

sigaddset(&set, SIGUSR1); 
// Block signal SIGUSR1 in this thread 
pthread_sigmask(SIG_BLOCK, &set, NULL); 
sigaddset(&set, SIGALRM); 
// Listen to signal SIGUSR2 
pthread_sigmask(SIG_UNBLOCK, &set, NULL); 


pthread_t printer_thread1, printer_thread2; 
pthread_create(&printer_thread1, NULL, print, (void *)&f1); 
pthread_create(&printer_thread2, NULL, print, (void *)&f2); 

bool tl = true; 
while(1) 
{ 
    if(tl) 
    { 
     // thread1 does something 
     kill(pid, SIGUSR1); 
     // main thread waits for SIGALRM 
     sigwait(&set, &sig); 
     tl = !tl; 
    } 
    else 
    { 
     // thread2 does something 
     kill(pid, SIGUSR2); 
     // main thread waits for SIGALRM 
     sigwait(&set, &sig); 
     tl = !tl; 
    } 
} 

我不允許使用Mutexs,信號燈等只有信號。

有人可以幫忙嗎? :)

+0

你不是第一次封鎖SIGUSR1嗎?在UNBLOCK時,該集合包含SIGUSR1和SIGALRM。 – amaurea

回答

9

有沒有辦法阻止某些信號並取消阻止其他信號在 同一組?

隨着pthread_sigmask,你可以選擇是:

  • 添加一組信號到設定阻斷信號,使用常量SIG_BLOCK
  • 刪除一組信號到設定的封鎖信號,使用恆定SIG_UNBLOCK
  • 定義所述一組信號被阻止,使用恆定SIG_SET

換句話說,線程有一組當前阻塞的信號,您可以按照上面的指定進行修改,一次只進行一個操作。

重要的一點是新創建的線程會繼承創建線程的信號掩碼,因此您可以在創建它之前或在新線程運行的函數中設置新線程的掩碼。

關於你的榜樣,我想,你想有printer_thread1SIGUSR2SIGALRM,並有printer_thread2SIGUSR1SIGALRM,並有主線程塊SIGUSR1SIGUSR2,使每個線程都可以發出一個信號,將被單線程捕獲(沒有print,f1f2的代碼,不可能知道你的例子中你的意圖是什麼)。

您應該能夠通過下面的代碼來實現這一目標:

sigset_t set; 
pthread_t printer_thread1, printer_thread2; 


// Block signal SIGUSR1 & SIGALRM in printer_thread1 
sigemptyset(&set); 
sigaddset(&set, SIGUSR1); 
sigaddset(&set, SIGALRM); 
pthread_sigmask(SIG_SET, &set, NULL); 
pthread_create(&printer_thread1, NULL, print, (void *)&f1); 

// Block signal SIGUSR2 & SIGALRM in printer_thread2 
sigaddset(&set, SIGUSR2); 
sigaddset(&set, SIGALRM); 
pthread_sigmask(SIG_SET, &set, NULL); 
pthread_create(&printer_thread2, NULL, print, (void *)&f2); 

// Block signal SIGUSR1 & SIGUSR2 in the main thread 
sigemptyset(&set); 
sigaddset(&set, SIGUSR1); 
sigaddset(&set, SIGUSR2); 
// Listen to signal SIGALRM 
pthread_sigmask(SIG_SET, &set, NULL); 


bool tl = true; 
while(1) 
{ 
    if(tl) 
    { 
     // thread1 does something 
     kill(pid, SIGUSR1); 
     // main thread waits for SIGALRM 
     sigwait(&set, &sig); 
     tl = !tl; 
    } 
    else 
    { 
     // thread2 does something 
     kill(pid, SIGUSR2); 
     // main thread waits for SIGALRM 
     sigwait(&set, &sig); 
     tl = !tl; 
    } 
} 

看到這些手冊頁:

進一步的細節。

+0

謝謝,這是有道理的,但它實際上不適用於打印機線程。但我明白現在面具如何工作。 – Max

1

我想你想在這裏做的是

// Block signal SIGUSR1 in this thread 
sigemptyset(&set); 
sigaddset(&set, SIGUSR1); 
pthread_sigmask(SIG_BLOCK, &set, NULL); 

// Listen to signal SIGALRM 
sigemptyset(&set); 
sigaddset(&set, SIGALRM); 
pthread_sigmask(SIG_UNBLOCK, &set, NULL); 

設定只是用來告訴它什麼阻止或允許。一旦傳遞給命令,您可以自由重置它並建立另一個信號掩碼。如果跳過sigemptyset,則該集合仍將包含SIGUSR1,隨後將再次解除阻塞。那麼,我認爲至少它是如何工作的 - 從我使用信號開始已經很長時間了。