В чем разница между информацией и сигналом?



Я собирался добавить дополнительный обработчик сигнала в приложение, которое мы имеем здесь, и я заметил, что автор использовал sigaction для настройки других обработчиков сигналов. Я собирался использовать сигнал. Чтобы следовать конвенции, я должен использовать sigaction, но если я писал с нуля, что я должен выбрать?

736   8  

8 ответов:

использовать sigaction() если у вас нет очень веских причин не делать этого.

The signal() интерфейс имеет древность (и, следовательно, доступность) в свою пользу, и это определено в стандарте C. Тем не менее, он имеет ряд нежелательных характеристик, которые sigaction() избегает - если вы не используете флаги, явно добавленные в sigaction() чтобы он точно имитировал старый signal() поведение.

  1. The signal() функция не блокирует (обязательно) поступление других сигналов во время выполнения текущего обработчика;sigaction() может блокировать другие сигналы, пока не вернется текущий обработчик.
  2. The signal() функция (обычно) сбрасывает действие сигнала обратно в SIG_DFL (по умолчанию) для почти всех сигналов. Это означает, что signal() обработчик должен переустановить себя в качестве первого действия. Он также открывает окно уязвимости между временем обнаружения сигнала и обработчиком переустановка, во время которой, если поступает второй экземпляр сигнала, происходит поведение по умолчанию (обычно завершается, иногда с предубеждением - aka core dump).
  3. точное поведение 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

    Ничего не найдено.