2012-10-10 36 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

小心阅读页面底部的音符......

信号处置的进程范围:如果安装了信号处理器,该处理器将在调用线程线程,但如果信号的处置是“停止”,“继续”或“终止”,则此操作将影响整个过程。

我如何解释这个过程的处理程序将被调用,然后您可以采取适当的措施,只要您满足这些条件,就知道该处理程序只是为该线程调用的。