Подтвердить что ты не робот

Работа с асинхронными сигналами в многопоточной программе

В книге интерфейса программирования Linux упоминался метод работы с асинхронными сигналами в многопоточной программе:

  • Все потоки блокируют все асинхронные сигналы, что процесс может получить. Самый простой способ сделать это блокирование сигналов в основная нить перед любой другой нитью создаются. Каждый впоследствии созданный нить наследует копию основного нить.
  • создать отдельный выделенный поток, который принимает входящие сигналы, используя sigwaitinfo(), sigtimedwait() или sigwait().

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

Теперь вопросы:

  • Когда ядро ​​хочет доставлять сигналы, он выбирает один из потоков внутри процесса произвольным. откуда он может знать, передать сигнал в выделенный поток?
  • API pthread - это несинхронные функции. так как мы можем использовать их внутри обработчика сигнала?
4b9b3361

Ответ 1

Когда ядро ​​доставляет сигнал, ориентированный на процесс, он выбирает один из потоков, который не блокирует сигнал. Это означает, что он никогда не выбирает ни одного из потоков, кроме потока обработки сигнала (который действует так, как будто он разблокирован, когда он заблокирован в sigwaitinfo() или аналогичном). Другими словами: ядро ​​знает, где подавать сигнал, потому что вы уложили такие вещи, что поток обработки сигналов - это единственный поток, которому когда-либо разрешалось доставлять сигнал.

В обработчике сигналов вы не используете API-интерфейс pthreads или любые несинхронные сигнальные функции. Вышеописанное решение не обрабатывает сигналы в обработчиках сигналов - оно обрабатывает сигналы в нормальном потоке выполнения потока обработки сигнала, после возврата sigwaitinfo(). Это позволяет ему получать доступ к не-асинхронным сигнальным функциям, что является целым.

Ответ 2

Помните, что предложение состоит в том, чтобы заблокировать сигнал (используя pthread_sigmask()) на ранней стадии выполнения процесса, прежде чем вы создадите какие-либо потоки или получите какие-либо сигналы.

Чтобы ответить на ваши вопросы:

  • Прочтите справочную страницу sigwait() (и/или sigwaitinfo()). Когда ядро ​​хочет отправить ваш процесс сигнал, но весь поток блокирует сигнал, сигнал становится "поставленным в очередь". Он остается в очереди до тех пор, пока либо (a) нить не разблокирует сигнал; или (b) некоторые потоковые вызовы sigwait() или sigwaitinfo() в сигнале. Предложение состоит в том, чтобы выделить поток для последнего.

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

Ответ 3

Вы можете косвенно вызывать API-интерфейсы pthread из обработчика сигнала с использованием другого механизма. В основном потоке создайте сокет домена Unix, который прослушивает определенные команды. Обработчик сигнала может иметь код для подключения к сокете и отправки команд в основной поток для вызова API-интерфейса pthread, который вы хотите вызвать.