В книге интерфейса программирования Linux упоминался метод работы с асинхронными сигналами в многопоточной программе:
- Все streamи блокируют все асинхронные сигналы, которые может получить этот процесс. Самый простой способ сделать это – заблокировать сигналы в основном streamе до создания любого другого streamа. Каждый впоследствии созданный stream наследует копию сигнальной маски основного streamа.
- создайте отдельный выделенный stream, который принимает входящие сигналы, используя
sigwaitinfo()
,sigtimedwait()
илиsigwait()
.Преимущество такого подхода заключается в том, что синхронно поступают асинхронно генерируемые сигналы. Поскольку он принимает входящие сигналы, выделенный stream может безопасно изменять общие переменные (под управлением мьютекса) и вызывать неасинхронные функции. Он также может сигнализировать переменные состояния и использовать другие механизмы связи и синхронизации streamов и процессов.
Теперь вопросы:
Когда kernel доставляет сигнал, ориентированный на процесс, он выбирает один из streamов , который не блокирует сигнал . Это означает, что он никогда не выбирает ни одного из streamов, кроме streamа обработки сигнала (который действует так, как будто он имеет разблокированный сигнал, когда он заблокирован в sigwaitinfo()
или аналогичном). Другими словами: kernel знает, куда подавать сигнал, потому что вы уложили такие вещи, чтобы stream обработки сигналов был единственным streamом, которому когда-либо позволяли доставлять сигнал.
Вы не используете API-интерфейс pthreads или любые функции, не связанные с асинхронным сигналом, в обработчике сигналов. Вышеописанное решение не обрабатывает сигналы в обработчиках сигналов – оно обрабатывает сигналы в нормальном streamе выполнения streamа обработки сигнала после sigwaitinfo()
. Это позволяет ему получать доступ к не-асинхронным сигнальным функциям, что является целым.
Помните, что предложение состоит в том, чтобы заблокировать сигнал (используя pthread_sigmask ()) на ранней стадии выполнения процесса, прежде чем вы создадите какие-либо streamи или получите какие-либо сигналы.
Чтобы ответить на ваши вопросы:
Прочтите страницу man для sigwait () (и / или sigwaitinfo () ). Когда kernel хочет отправить ваш процесс сигнал, но весь stream блокирует сигнал, сигнал становится «поставленным в очередь». Он остается в очереди до тех пор, пока либо (a) нить не разблокирует сигнал; или (b) некоторые streamовые вызовы sigwait () или sigwaitinfo () в сигнале. Предложение здесь состоит в том, чтобы выделить stream для последнего.
Идея заключается в том, что вы никогда не запускаете никаких обработчиков сигналов, потому что нить никогда не блокирует сигнал. Вместо этого один stream ожидает сигнала с помощью sigwait (), а затем обрабатывает сигнал. Все это происходит вне контекста обработки сигналов, что является красотой предложения.
Вы можете косвенно вызывать API-интерфейсы pthread из обработчика сигнала с использованием другого механизма. В основном streamе создайте сокет домена Unix, который прослушивает определенные команды. Обработчик сигнала может иметь код для подключения к сокете и отправки команд в основной stream для вызова API-интерфейса pthread, который вы хотите вызвать.