Скажем, у меня есть поток 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(...){...}
А если нет, то какова альтернатива.
Вы можете отправить сигнал определенной теме, используя 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
, Они имеют дополнительное преимущество, заключающееся в том, что более чем один из них может одновременно находиться на рассмотрении. Они гораздо лучше подходят для такого рода вещей, чем традиционные сигналы.
И да и нет.
Новым для меня является функция pthread_kill (), которая позволяет отправлять сигналы потокам в рамках одного и того же процесса.
http://linux.die.net/man/3/pthread_kill
Внимательно прочитайте заметки внизу страницы …
Расположение сигналов распространяется на весь процесс: если установлен обработчик сигнала, обработчик будет вызываться в потоке потока, но если расположение сигнала равно «стоп», «продолжить» или «завершить», это действие повлияет на весь процесс.
Я понимаю, что будет вызван обработчик процесса, и тогда вы сможете предпринять соответствующие действия, зная, что обработчик вызывался только для этого потока, если вы удовлетворяете этим условиям.