我可以向不同的线程发送信号吗

pyt*_*nic 4 c c++ linux x86 gcc

假设我有一个线程 A,它想向线程 B、C 和 D 发送信号。我可以做这样的事情吗?

SendSignalTo( ThreadB, SIGUSR1 );
SendSignalTo( ThreadC, SIGUSR1 );
SendSignalTo( ThreadD, SIGUSR1 );
Run Code Online (Sandbox Code Playgroud)

使用 SIGUSR1 信号处理程序,为线程 B、C 和 D 定义不同,如下所示。

void SIGUSR1_Handler_for_ThreadB(...){...}
void SIGUSR1_Handler_for_ThreadC(...){...}
void SIGUSR1_Handler_for_ThreadD(...){...}
Run Code Online (Sandbox Code Playgroud)

如果没有,还有什么选择。

Nom*_*mal 5

您可以使用 向特定线程发送信号pthread_kill(),或者如果您不介意特定于 GNU,则使用pthread_sigqueue()(可以指定一个intvoid *处理程序可以通过 访问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);
}
Run Code Online (Sandbox Code Playgroud)

原子负载 ( __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));
Run Code Online (Sandbox Code Playgroud)

__sync_fetch_and_or()和功能开关既可以通过一个C ++ 11式所取代__atomic_电话,但我没有GCC最近还不够,所以我仍然使用旧式__sync_电话。

POSIX 还支持实时信号,SIGRTMIN+0, SIGRTMIN+1, .., SIGRTMAX. 它们还有一个额外的好处,即可以同时挂起不止一个。它们比传统信号更适合这种事情。