2013-09-24 84 views
1

我是C中的新手。我想創建一個程序,其中包含兩個線程,它們將在一個循環中發送信號(SIGUSR1和SIGNUSR2),並且將等待這些信號並處理這四個線程他們。線程等待信號在一個循環中

我明白髮送信號我需要做的:kill(getpid,SIGUSR1);但如何創建四個線程,將等待信號?該信號被註冊到特定功能。四個線程如何等待相同的信號?

我可以有其他線程檢查信號的類型也(不停止信號到達其他線程)?

謝謝。


更新:
我想有四個線程在等待信號,當兩個線程發送信號,線程不知道哪個線程將捕獲的信號。我不想指定將接收信號的線程ID。

當使用pthread_kill()我需要指定線程ID(我試圖不這樣做)。

+0

的手冊頁是否有一個原因,你必須使用信號(看起來像同步問題)? – jev

+0

你是什麼意思的「隨機過程」?您可以爲每個線程設置信號掩碼,只允許信號到達某些線程,然後使用'kill'讓內核選擇一個任意的隨機線程來接收信號。或者您可以主動枚舉所有線程,使用隨機數生成器從中選擇,併發送定向信號。 –

+0

@KerrekSB,我可以同時向兩個進程發送一個信號,並且哪個有空可以處理這個信號?或者我可以創建屬於同一組的少量進程並將信號發送給整個組? – Mike

回答

2

更新:這個答案可能是部分無用的。您應該使用pthread_kill將信號發送到特定的線程。但是,如果有人發現某些東西,我會留下來。


在Linux中,線程不能與kill處理,因爲kill將信號發送到任何隨機線程不阻止信號。

取而代之,您需要系統調用tgkill,它針對特定的線程。哪個線程?您可以通過系統調用gettid找到答案。

不幸的是,glibc沒有爲這兩個系統調用提供包裝。沒問題,你可以寫自己的那些:

#include <signal.h> 
#include <sys/syscall.h> 
#include <sys/types.h> 

pid_t gettid() 
{ 
    return syscall(SYS_gettid); 
} 

int tgkill(int sig, pid_t pgid, pid_t tid) 
{ 
    return syscall(SYS_tkill, sig, pgid, tid); 
} 

tgkill的第一個參數是信號,如爲kill。第二個是線程組號,它與您的進程的進程ID相同(可通過getpid獲得)。最後一個參數是內核線程ID,您可以通過gettid獲得內核線程ID,它也構成Linux上/proc/<pid>/task/中的目錄。

最後,您需要能夠等待信號到達。您可以通過與pthread_sigmask,然後使用sigwaitinfo or sigtimedwait阻塞線程的信號做到這一點:

// block signal 
sigset_t newset, oldset; 
sigemptyset(&nweset); 
sigaddset(&newset, SIGUSR1); 
pthread_sigmask(SIG_BLOCK, &newset, &oldset); 

// wait 
sigwaitinfo(&newset, NULL); 

// restore previous signal mask 
pthread_sigmast(SIG_SETMASK, &oldset, NULL); 
+0

感謝您的好評。但是,我是否指定了我發送信號的線程?我怎麼知道哪個線程會抓住它?另外,如何在循環中發送信號? – Mike

+0

@Mike:在所需的線程中使用'gettid'!不過,我不確定您是否可以獲取* * *線程的線程ID。您可以枚舉'/ proc//task /',並排除您自己的線程ID以查看其他所有內容。或者讓每個新線程發回一個信號(檢查文檔,您可以在siginfo部分添加數據)。 –

+0

只是在創建線程時保留線程的ID是另一個顯而易見的選擇。 –

0

我真的不建議使用SIGUSR信號的線程同步。如果你想pthreads等待一個信號,我會看看pthread_cond_signal