Sigsuspend эквивалентен атомному ряду sigprocmask, pause, sigprocmask?

#c #exception #signals #signal-handling #multiple-processes

#c #исключение #сигналы #обработка сигналов #многопроцессорный

Вопрос:

Я читал главу моего учебника (CS: APP, 3-е изд., глава 8, стр. 781) о сигналах / ECF для систем Linux x86-64 и наткнулся на это:

Функция sigsuspend временно заменяет текущий заблокированный набор на mask, а затем приостанавливает процесс до получения сигнала, действие которого заключается либо в запуске обработчика, либо в завершении процесса. Если действие должно завершиться, то процесс завершается без возврата из sigsuspend . Если действие заключается в запуске обработчика, то sigsuspend возвращается после возврата обработчика, восстанавливая заблокированный набор в его состояние, когда был вызван sigsuspend.

Функция sigsuspend эквивалентна атомарной (бесперебойной) версии следующего:

 1       sigprocmask(SIG_BLOCK, amp;mask, amp;prev);
2       pause();
3       sigprocmask(SIG_SETMASK, amp;prev, NULL);
 

Насколько я понимаю, это sigprocmask(SIG_BLOCK, amp;mask, amp;prev) должно привести к тому, что заблокированный набор будет упорядочен с помощью маски, т. Е. Добавление сигналов в маске к тем, которые уже есть в заблокированном наборе. Но в тексте непосредственно над кодом (и на справочной странице для sigsuspend, которую я просмотрел) говорится, что sigsuspend «временно заменяет текущий заблокированный набор на mask». Для меня это больше похоже sigprocmask(SIG_SETMASK, amp;mask, amp;prev) на то, что заблокированный набор просто устанавливается равным сигналам в маске.

Итак, почему это sigsuspend(amp;mask) эквивалентно приведенному выше коду (строки 1-3), а не коду ниже (строки 4-6)? Где я ошибся в своей интуиции и / или понимании функций signal.h?

 4       sigprocmask(SIG_SETMASK, amp;mask, amp;prev);
5       pause();
6       sigprocmask(SIG_SETMASK, amp;prev, NULL);
 

Если я не совсем ясно, позвольте мне вместо этого задать конкретный вопрос (это может лучше объяснить мою интуицию). Скажем, текущий заблокированный набор кодирует SIGCHLD, а маска sigset_t кодирует SIGINT . Я вызываю sigsuspend(amp;mask) . Независимо от того, какая интерпретация кода верна (строки 1-3 ИЛИ 4-6), сигнал SIGINT, доставленный сразу после вызова sigsuspend, будет заблокирован / не будет запускать процесс. Однако, что, если сразу после вызова sigsuspend будет доставлен сигнал SIGCHLD? Будет ли процесс просыпаться / получать сигнал? Моя интуиция говорит, что строки 1-3 будут блокировать SIGCHLD, а строки 4-6 — нет, поэтому очевидно, что строки 1-3 и 4-6 не эквивалентны. Но моя интуиция также говорит, что sigsuspend не должен блокировать SIGCHLD, потому что он не в маске, поэтому строки 4-6 верны, и если строки 4-6 эквивалентны sigsuspend в этом случае, sigsuspend не может быть эквивалентен строкам 1-3. Где моя интуиция / понимание пошло не так?

Комментарии:

1. Ну, теперь я чувствую себя немного глупо. Я не привык к ошибкам в учебниках, мне никогда бы не пришло в голову искать исправления, внесенные в книгу. Я проверю это в будущем. Спасибо!

2. Полезный совет: если ваш профессор является автором этого учебника, затрагивайте эту тему очень деликатно или не затрагивайте ее вообще.

3. Возможно, вы захотите принять ответ Марка ниже?

Ответ №1:

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

Эта ссылка для исправлений для этой книги показывает:

Глава 8: Исключительный поток управления


стр. 781. В описании sigsuspend во втором абзаце строка 1 должна быть:
sigprocmask(SIG_SETMASK, amp;mask, amp;prev);
Опубликовано 28.10.2015. Дэйв О’Халларон