Отправить и поймать сигналы в pthreads в C - PullRequest
11 голосов
/ 17 ноября 2010

Я знаю, как отправлять сигналы дочернему процессу в C, используя функцию kill(pid_t pid, int sig). Как насчет отправки сигналов в потоки? Является ли это возможным?. Если так, то как ловить сигналы на «дочернем» потоке. Например, если основной поток посылает мне сигнал завершения, как я могу его перехватить в другом потоке.

Ответы [ 4 ]

8 голосов
/ 17 ноября 2010

В потоках 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,с той же условной переменной.

Учитывая аналогию с сигналами, доставляемыми процессам, это немного отличается, потому что сигнальный поток уже приостановил свое выполнение в ожидании сигнала, в отличие от процесса, который просто прерывается и продолжается.

7 голосов
/ 18 ноября 2010

Сигналы отправляются процессу в целом.Каждый сигнал, отправленный процессу, принимается одним потоком (от имени всей программы).Существуют маски сигналов для каждого потока, которые влияют на то, подходит ли конкретный поток для обработки определенного сигнала.

Итак, вам нужен обработчик сигнала - возможно, только в одном потоке.Обратите внимание, что существуют ограничения на то, что вы должны делать в обработчике сигналов потока.Будьте осторожны, выходя далеко за рамки обещаний, данных стандартом (которые минимальны).

Однако функцию pthread_kill() можно использовать для отправки сигналов другим потокам, еслитекущий поток может идентифицировать (имеет доступ к значениям идентификатора потока (pthread_t), которые идентифицируют) потоки, которые все еще выполняются в процессе.Вы можете решить передать сигнал другим потокам, используя номер сигнала, отличный от первоначально отловленного (поэтому один поток получает внешний сигнал, но многие потоки получают внутренний сигнал).Или вместо сигналов вы можете использовать другой примитив синхронизации или связи Pthread.

2 голосов
/ 17 ноября 2010

Сигналы не имеют сходства потоков. Они обрабатываются полностью асинхронно. Когда вы определяете обработчик сигнала с помощью signal(2) или sigaction(2), это глобальный обработчик сигнала. Когда сигнал повышается, обработчик сигнала запускается поверх стека любого потока, который выполняется в данный момент, и вы не можете это контролировать.

Звучит так, будто вы хотите какой-то другой вид межпотоковой коммуникации Самый простой способ сделать это с помощью общей переменной volatile:

volatile bool should_terminate = false;

void ChildThread()
{
    while(!should_terminate)
    {
        // do stuff
    }
}

void MainThread()
{
    // To terminate child thread:
    should_terminate = true;
}

Если вам нужен более сильный контроль параллелизма, посмотрите на мьютексы, условные переменные и семафоры.

0 голосов
/ 17 ноября 2010

Я не уверен, что это возможно, поскольку это зависит от платформы и реализации, и я настоятельно рекомендую вам не использовать сигналы для связи между потоками.Иногда только определенный поток будет получать сигналы, а иногда все потоки получают сигналы.

Существуют более совершенные механизмы связи потоков, такие как очереди, семафоры и блокировки.

...