В чем разница между информацией и сигналом?
Я собирался добавить дополнительный обработчик сигнала в приложение, которое мы имеем здесь, и я заметил, что автор использовал sigaction для настройки других обработчиков сигналов. Я собирался использовать сигнал. Чтобы следовать конвенции, я должен использовать sigaction, но если я писал с нуля, что я должен выбрать?
8 ответов:
использовать
sigaction()если у вас нет очень веских причин не делать этого.The
signal()интерфейс имеет древность (и, следовательно, доступность) в свою пользу, и это определено в стандарте C. Тем не менее, он имеет ряд нежелательных характеристик, которыеsigaction()избегает - если вы не используете флаги, явно добавленные вsigaction()чтобы он точно имитировал старыйsignal()поведение.
- The
signal()функция не блокирует (обязательно) поступление других сигналов во время выполнения текущего обработчика;sigaction()может блокировать другие сигналы, пока не вернется текущий обработчик.- The
signal()функция (обычно) сбрасывает действие сигнала обратно вSIG_DFL(по умолчанию) для почти всех сигналов. Это означает, чтоsignal()обработчик должен переустановить себя в качестве первого действия. Он также открывает окно уязвимости между временем обнаружения сигнала и обработчиком переустановка, во время которой, если поступает второй экземпляр сигнала, происходит поведение по умолчанию (обычно завершается, иногда с предубеждением - aka core dump).- точное поведение
signal()варьируется между системами и нормами разрешение на эти изменения.они, как правило, веские причины для использования
sigaction()вместоsignal(). Однако, интерфейсsigaction()- Это, несомненно, сложнее.какой бы из двух вы используете, не соблазнитесь альтернативными сигнальными интерфейсами, такими как
sighold(),sigignore(),sigpause()иsigrelse(). Они номинально являются альтернативамиsigaction(), но они едва стандартизированы и присутствуют в POSIX для обратной совместимости, а не для серьезного использования. Обратите внимание, что стандарт POSIX говорит, что их поведение в многопоточных программах не определено.многопоточные программы и сигналы-это целое другая запутанная история.
насколько я знаю, какsignal()иsigaction()ОК в многопоточных приложениях.man-страница Linux для
signal()говорит:
эффектыsignal()в многопоточном процессе не указаны.таким образом, я думаю
sigaction()- Это единственное, что можно безопасно использовать в многопоточном процессе.это интересно. В этом случае страница руководства Linux является более ограничительной, чем POSIX. В POSIX для
signal():если процесс многопоточный, или если процесс однопоточный и обработчик сигнала выполняется иначе, чем в результате:
- процесс
abort(),raise(),kill(),pthread_kill()илиsigqueue()для генерации сигнала, который не заблокирован- ожидающий сигнал разблокируется и доставляется до вызова, который разблокировал он возвращает
поведение не определено, если обработчик сигнала ссылается на любой объект, отличный от
errnoсо статической продолжительностью хранения, отличной от присвоения значения объекту, объявленному какvolatile sig_atomic_t, или если обработчик сигнала вызывает любую функцию, определенную в этом стандарте, кроме одной из функций, перечисленных в сигнал Понятия.таким образом, POSIX четко определяет поведение
signal()в многопоточном приложении.тем не менее
sigaction()является предпочтительным по существу во всех обстоятельствах-и портативный многопоточный код должен использоватьsigaction()Если нет подавляющей причины, по которой он не может (например, "использовать только функции, определенные стандартом C" - и да, код C11 может быть многопоточным). Что в основном и является первым абзацем этого ответа говорит.
Это разные интерфейсы для сигнальных устройств ОС. Следует предпочесть использовать sigaction для сигнала, если это возможно, поскольку signal () имеет определенное реализацией (часто склонное к гонке) поведение и ведет себя по-разному в Windows, OS X, Linux и других системах UNIX.
посмотреть этот безопасность для сведения.
для меня этого ниже строки было достаточно, чтобы решить:
функция sigaction() обеспечивает более всесторонний и надежный механизм управления сигналами; новый приложения должны использовать sigaction() а не сигнал()
http://pubs.opengroup.org/onlinepubs/009695399/functions/signal.html#tag_03_690_07
независимо от того, начинаете ли вы с нуля или изменяете старую программу, sigaction должен быть правильным выбор.
С
signal(3)man page:описание
This signal() facility is a simplified interface to the more general sigaction(2) facility.использовать один и тот же базовый объект. По-видимому, вы не должны манипулировать ответом на один сигнал с обоими, но смешивание их не должно приводить к нарушению...
Я бы использовал signal (), так как он более портативен, по крайней мере теоретически. Я проголосую за любого комментатора, который может придумать современную систему, которая не имеет уровня совместимости POSIX и поддерживает signal().
слово документация GLIBC:
можно использовать как функции сигнала, так и функции sigaction внутри одной программы, но вы должны быть осторожны, потому что они могут взаимодействуйте немного странным образом.
функция sigaction указывает больше информации, чем сигнал функция, поэтому возвращенное значение от сигнала не может выразить вполне диапазон возможностей sigaction. Поэтому, если вы используете сигнал сохраните и позже восстановите действие, возможно, оно не сможет восстановите правильно обработчик, который был установлен с помощью sigaction.
чтобы избежать проблем в результате, всегда используйте sigaction для сохранения и восстановите обработчик, если ваша программа вообще использует sigaction. С sigaction является более общим, он может правильно сохранять и восстанавливать любые действие, независимо от того, было ли оно установлено изначально с помощью сигнал или вызов sigaction.
на некоторых системах, если вы устанавливаете действие с сигнала, а затем изучите его с помощью sigaction, адрес обработчика, который вы получаете, может не быть быть таким же, как то, что вы указали с сигналом. Это может даже не быть подходит для использования в качестве аргумента действия с сигналом. Но вы можете положиться использовать его в качестве аргумента sigaction. Эта проблема никогда не происходит в системе GNU.
Итак, вам лучше использовать один или другой из механизмов последовательно в рамках одной программы.
портативность Примечание: основная функция сигнала является особенностью ISO C, в то время как sigaction является частью POSIX.Стандарт 1. Если вы не беспокоясь о переносимости в системах, отличных от POSIX, вы должны вместо этого используйте функцию сигнала.
Авторское Право (C) 1996-2008 Бесплатно Software Foundation, Inc.
разрешение предоставляется на копирование, распространение и / или изменение этого документ на условиях лицензии GNU Free Documentation, Версии 1.2 или любой более поздней версией, опубликованной Free программное обеспечение Фундамент; без инвариантных разделов, без текстов на обложке, и без текстов на задней обложке. Копия лицензии входит в комплект поставки раздел "Лицензия Свободной документации GNU".
сигнал() является стандартным C, sigaction () нет.
Если вы можете использовать либо (то есть вы находитесь в системе POSIX), то используйте sigaction(); не указано, сбрасывает ли signal() обработчик, что означает, что для переносимости вам нужно снова вызвать signal() внутри обработчика. Хуже всего то, что есть гонка: если вы получаете два сигнала в быстрой последовательности, а второй доставляется до переустановки обработчика, у вас будет действие по умолчанию, которое, вероятно, будет чтобы убить процесс. sigaction (), С другой стороны, гарантируется использование "надежных" семантика сигнала. Вам не нужно переустановить обработчик, потому что он никогда не будет сброшен. С помощью SA_RESTART вы также можете получить некоторые системные вызовы для автоматического перезапуска (поэтому вам не нужно вручную проверять EINTR). sigaction () имеет больше возможностей и является надежным, поэтому его использование рекомендуется.
Psst... не говорите никому, что я сказал вам это, но POSIX в настоящее время имеет функцию bsd_signal (), который действует как signal (), но дает семантику BSD, что означает, что он надежен. Его основное использование - для переноса старых приложений, которые предполагали надежные сигналы, и POSIX не рекомендует его использовать.
Я бы также предложил использовать sigaction() над signal () и хотел бы добавить еще одну точку. sigaction () дает вам больше возможностей, таких как pid процесса, который умер (возможно, используя структуру siginfo_t).
из man page сигнал(7)
процесс-направленный сигнал может быть доставлен в любой один из потоков, который в настоящее время не имеет сигнала заблокирован. Если более чем один из потоков имеет сигнал разблокирован, то ядро выбирает произвольный поток, в который будет подаваться сигнал.
и я бы сказал, что эта "проблема" существует для Сигнал(2) и sigaction (2). Так что будьте осторожны с сигналами и компиляции.
... и Сигнал(2) Кажется, назвал sigaction (2) внизу в Linux с glibc.
Comments