您可以将信号发送到使用pthread_kill()
特定线程,或者如果你不介意被GNU专用,使用pthread_sigqueue()
(可以指定一个int
或void *
处理程序可以通过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+0
,SIGRTMIN+1
,..,SIGRTMAX
。他们还有额外的好处,即他们中的一个以上可以同时待决。它们比传统信号更适合这种事物。
信号并不是那么棒。在Linux上,您可以使用eventfds进行通信,并让每个线程在其各自的fd上运行一个'epoll'循环。这对于负载均衡也很有用,因为您可以有多个线程等待* same * eventfd,并且确保* one *被保证唤醒。 –
@KerrekSB这实际上是一个非常好的解决方案,如果你不挖掘不可移植性。伟大的发现! –