4

假设我有一个线程 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(...){...}

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

4

2 回答 2

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);
}

原子加载 ( __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. 它们还有一个额外的好处,即它们中的一个以上可以同时挂起。它们比传统信号更适合这种事情。

于 2012-10-10T16:15:11.537 回答
4

是和不是。

对我来说新的是 pthread_kill() 函数,它允许您向同一进程下的线程发送信号。

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

请注意阅读页面底部的注释...

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

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

于 2012-10-10T13:44:36.633 回答