Я знаю, как отправлять сигналы дочернему процессу на C с помощью функции kill(pid_t pid, int sig)
. Как насчет отправки сигналов в потоки? Является ли это возможным?. Если да, то как поймать сигналы по "дочерней" нити. Например, если основной поток отправляет мне сигнал о завершении, как я могу в другом потоке поймать его.
Передача и улавливание сигналов на pthreads в C
Ответ 1
С потоками POSIX у вас есть функции pthread_cond_wait
и pthread_cond_signal
.
int pthread_cond_wait(pthread_cond_t *restrict cond, pthread_mutex_t *restrict mutex)
int pthread_cond_signal(pthread_cond_t *cond)
Сигнальный поток должен блокировать вызов pthread_cond_wait
, пока другой поток не отправит сигнал с помощью pthread_cond_signal
с той же переменной условия.
Учитывая аналогию с сигналами, передаваемыми процессам, это немного отличается, потому что сигнальный поток уже приостановил выполнение, ожидая сигнала, в отличие от процесса, который просто прерывается и продолжается.
Ответ 2
Сигналы отправляются процессу в целом. Каждый сигнал, отправленный в процесс, принимается одним потоком (от имени всей программы). Существуют маски сигналов на потоке, которые влияют на то, имеет ли конкретный поток право обрабатывать конкретный сигнал.
Итак, вам нужен обработчик сигнала - возможно, только в одном потоке. Обратите внимание, что существуют ограничения на то, что вы должны делать в обработчике сигнала потока. Будьте осторожны, выходя далеко за пределы promises, сделанные стандартом (минимальные).
Тем не менее, функция pthread_kill()
может использоваться для отправки сигналов другим потокам, пока текущий поток может идентифицировать (имеет доступ к значениям идентификатора потока (pthread_t
), которые идентифицируют) потоки, которые все еще выполняются в процессе. Вы можете решить передать сигнал другим потокам, используя другой номер сигнала от первоначально обнаруженного (так что один поток принимает внешний сигнал, но многие потоки принимают внутренний сигнал). Или вы можете использовать другой сигнал синхронизации Pthread или коммуникационный примитив вместо сигналов.
Ответ 3
Сигналы не имеют сходства нитей. Они обрабатываются полностью асинхронно. Когда вы указываете обработчик сигнала с signal(2)
или sigaction(2)
, это глобальный обработчик сигналов. Когда сигнал поднимается, обработчик сигнала работает поверх стека любого потока, который будет выполняться в то время, и вы не можете его контролировать.
Похоже, вам нужно другое другое сообщение interthread. Самый простой способ сделать это - с помощью volatile
shared variable:
volatile bool should_terminate = false;
void ChildThread()
{
while(!should_terminate)
{
// do stuff
}
}
void MainThread()
{
// To terminate child thread:
should_terminate = true;
}
Если вам нужен более сильный элемент управления concurrency, посмотрите на мьютексы, переменные условия и семафоры.
Ответ 4
Я не уверен, что это возможно, поскольку это зависит от платформы и реализации, и я настоятельно рекомендую вам не использовать сигналы для связи между потоками. Иногда только конкретный поток получает сигналы, а иногда все потоки принимают сигналы.
Улучшены механизмы коммуникации потока, такие как очереди, семафоры и блокировки.