• Сигналы, которые игнорируются, продолжают игнорироваться. Особым случаем является SIGCHLD
SIGCHLD
до вызова exec()
игнорировался, он может игнорироваться также и после вызова. В качестве альтернативы для него может быть восстановлено действие по умолчанию. То, что происходит на самом деле, стандартом POSIX намеренно не определяется. (Справочные страницы GNU/Linux не определяют, что делает Linux, и поскольку POSIX оставляет это не определенным, любой код, который вы пишете для использования SIGCHLD
, должен быть подготовлен для обработки любого случая.)• Сигналы, заблокированные до вызова exec()
• Любые ожидающие сигналы (те, которые появились, но были заблокированы) сбрасываются. Новая программа не может их получить.
• Временной интервал, остающийся для alarm()
alarm
, а затем непосредственно вызывает exec()
, новый образ в конечном счете получит SIGALARM
. Если он сначала вызывает fork()
, родитель сохраняет установки alarm
, тогда как потомок, вызывающий exec()
, не сохраняет.ЗАМЕЧАНИЕ
. Многие, если не все. программы предполагают, что сигналы инициализированы действиями по умолчанию и что заблокированных сигналов нет. Таким образом, особенно если не вы писали программу, запускаемую с помощьюexec()
, можно разблокировать перед вызовам exec()
все сигналы10.10. Резюме
«Наша история до настоящего времени, эпизод III»
• Интерфейсы обработки сигналов развились от простых, но подверженных состояниям гонок, до сложных, но надежных. К сожалению, множественность интерфейсов затрудняет их изучение по сравнению с другими API Linux/Unix.
• У каждого сигнала есть связанное с ним действие. Действие может быть одним из следующих: игнорирование сигнала; выполнение действия системы по умолчанию или вызов предоставленного пользователем обработчика. Действие системы по умолчанию, в свою очередь, является одним из следующих: игнорирование сигнала, завершение процесса; завершение процесса с созданием его образа; остановка процесса или возобновление процесса, если он остановлен.
• signal()
raise()
стандартизованы ISO С. signal()
управляет действиями для определенных сигналов; raise()
посылает сигнал текущему процессу. Остаются ли обработчики сигналов установленными после вызова или сбрасываются для действия по умолчанию, зависит от реализации, signal()
и raise()
являются простейшими интерфейсами, для многих приложений их достаточно.• POSIX определяет функцию bsd_signal()
signal()
, но гарантирует, что обработчик остается установленным.• Действия, происходящие после возвращения из обработчика, варьируют в зависимости от системы. Традиционные системы (V7, Solaris, возможно, и другие) восстанавливают действие сигнала по умолчанию. На этих системах прерванный системный вызов возвращает -1, устанавливая в errno
EINTR
. Системы BSD оставляют обработчик установленным и возвращают -1 с errno
, содержащим EINTR
, лишь в случае, когда не было перемещения данных; в противном случае, системный вызов запускается повторно.• GNU/Linux придерживается POSIX, который похож, но не идентичен с BSD. Если не было перемещения данных, системный вызов возвращает -1/EINTR
sigaction()
, но он не является действием по умолчанию.• Обработчики сигналов, используемые с signal()
volatile sig_atomic_t
. (В целях упрощения в некоторых из наших примеров мы не всегда следовали этому правилу.) Таким же образом, для вызова из обработчика сигналов безопасными являются лишь функции из табл. 10.2.• Первоначальной попыткой создания надежных сигналов был API сигналов System V Release 3 (скопированный из BSD 4.0). Не используйте его в новом коде.
• POSIX API содержит множество компонентов:
• маску сигналов процесса, перечисляющую текущие заблокированные сигналы;
• тип sigset_t
sigfillset()
, sigemptyset()
, sigaddset()
, sigdelset()
и sigismember()
для работы с ними; • функцию sigprocmask()