您可以使用 向特定线程发送信号pthread_kill()
,或者如果您不介意特定于 GNU,则可以使用pthread_sigqueue()
(可以指定一个int
或void *
处理程序可以通过 访问info->si_value
)。
进程的每个信号只有一个信号处理程序。这意味着特定信号将始终调用相同的处理函数,无论它碰巧是哪个线程。如果一个线程设置了新的信号处理程序,则信号处理程序将为所有线程更改。
但是,解决方法很简单:使用每个线程的函数指针来定义信号处理程序应该调用哪个函数。请记住信号处理程序的限制——您只能在信号处理程序中使用异步信号安全函数。
/* 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
. 它们还有一个额外的好处,即它们中的一个以上可以同时挂起。它们比传统信号更适合这种事情。