2012-10-10 68 views
3

說我有一個線程A,它想要發送信號給線程B,C和D.我可以做這樣的事情。我可以發送信號給不同的線程

SendSignalTo(ThreadB, SIGUSR1); 
SendSignalTo(ThreadC, SIGUSR1); 
SendSignalTo(ThreadD, SIGUSR1); 

使用SIGUSR1信號處理程序,針對線程B,C和D定義不同,如下所示。

void SIGUSR1_Handler_for_ThreadB(...){...} 
void SIGUSR1_Handler_for_ThreadC(...){...} 
void SIGUSR1_Handler_for_ThreadD(...){...} 

如果不是,那麼有什麼選擇。

+0

信號並不是那麼棒。在Linux上,您可以使用eventfds進行通信,並讓每個線程在其各自的fd上運行一個'epoll'循環。這對於負載均衡也很有用,因爲您可以有多個線程等待* same * eventfd,並且確保* one *被保證喚醒。 –

+0

@KerrekSB這實際上是一個非常好的解決方案,如果你不挖掘不可移植性。偉大的發現! –

回答

3

您可以將信號發送到使用pthread_kill()特定線程,或者如果你不介意被GNU專用,使用pthread_sigqueue()(可以指定一個intvoid *處理程序可以通過info->si_value訪問)。

每個信號只有一個信號處理程序。這意味着一個特定的信號將總是調用相同的處理函數,而不管它發生在哪個線程中。如果一個線程設置了新的信號處理程序,則信號處理程序將針對所有線程更改。

但是,解決方法很簡單:使用每線程函數指針來定義信號處理程序應該調用哪個函數。請記住信號處理程序的限制 - 您只能在信號處理程序中使用async-signal safe functions

/* Simplify by defining the signal handler function type, assume SA_SIGINFO */ 
typedef void (*signal_handler_t)(int, siginfo_t *, void *); 

/* Per-thread variable pointing to the desired function */ 
static __thread signal_handler_t thread_handler = NULL; 

/* Process-wide actual signal handler */ 
static void signal_handler(int signum, siginfo_t *info, void *context) 
{ 
    signal_handler_t func; 

    func = __sync_fetch_and_or(&thread_handler, (signal_handler_t)0); 

    if (func) 
      func(signum, info, context); 
} 

原子負載(__sync_fetch_and_or()),可以使用一個簡單的原子商店在任何時間點,甚至沒有阻塞信號平凡改變每個線程處理器。切換到功能new_thread_handler然後

signal_handler_t func; 

    do { 
     func = thread_handler; 
    } while (!__sync_bool_compare_and_swap(&thread_handler, func, new_thread_handler)); 

__sync_fetch_and_or()和功能開關既可以通過一個C++ 11式__atomic_調用所替換,但我沒有GCC最近還不夠,所以我仍然使用舊式__sync_來電。

POSIX還支持實時信號,SIGRTMIN+0SIGRTMIN+1,..,SIGRTMAX。他們還有額外的好處,即他們中的一個以上可以同時待決。它們比傳統信號更適合這種事物。

4

是的,沒有。

新手給我的是pthread_kill()函數,它允許你在同一個進程下向線程發送信號。

http://linux.die.net/man/3/pthread_kill

小心閱讀頁面底部的音符......

信號處置的進程範圍:如果安裝了信號處理器,該處理器將在調用線程線程,但如果信號的處置是「停止」,「繼續」或「終止」,則此操作將影響整個過程。

我如何解釋這個過程的處理程序將被調用,然後您可以採取適當的措施,只要您滿足這些條件,就知道該處理程序只是爲該線程調用的。