Почему программы Unix не могут иметь сигналы со значимыми именами, определенными для программ (вместо USR1 и т.д.)?

Многие программы Unix принимают сигналы типа USR1 и USR2. Например, чтобы обновить исполняемый файл для Nginx "на лету", вы отправляете kill -USR2.

Я понимаю, что USR1 является "определяемым пользователем" сигналом, что означает, что тот, кто создал программу, может использовать его для обозначения "выключить" или "выгрузить ваши журналы" или "распечатать foo тысячу раз" или что-то еще. Но я не понимаю, почему они должны использовать это произвольное имя. Почему бы не kill -UPGRADE, или kill -GRACEFUL_SHUTDOWN? Имеет ли Unix только определенные сигналы?

Пока мы это делаем, Nginx также использует следующие сигналы (см. документация):

  • TERM, INT: быстрое отключение
  • QUIT: изящное завершение работы
  • HUP:
    • Конфигурация перезагрузки
    • Запустите новые рабочие процессы с новой конфигурацией
    • Изящное завершение работы старых рабочих процессов
  • USR1: откройте файлы журнала
  • USR2: обновление исполняемых на лету
  • WINCH: изящное завершение рабочих процессов

HUP? Winch? Какая причина этих имен? Где я могу узнать больше об этом?

Ответ 1

Сигналы, доступные в ОС, определяются ОС (обычно после POSIX) - они не являются "строками", а целыми константами со стандартными именами. USR1 и USR2 - это два сигнала, которые не имеют конкретного значения, предназначенные для любого произвольного использования, которое хочет разработчик.

На вашей машине linux прочитайте man 7 signal для обзора обработки сигналов и сигналов.

Вы можете переопределить значение других сигналов, если вы готовы работать с ОС, выдавая эти сигналы в ответ на события. Вы можете, например, make HUP означает "перезагрузить конфигурацию" - если вы либо уверены, что процесс никогда не получит зависания (потеря терминала), либо вы готовы обрабатывать случаи, когда ОС, а не пользователь, посылает сигнал HUP.

Ответ 2

HUP не подходит для "зависания". Этот сигнал отправляется процессу, если его управляющий терминал достигает конца файла. В прежние времена управляющие терминалы обычно подключались к последовательным портам, возможно, через модемную линию по телефонной линии. Если телефонное соединение было повёрнуто, локальный модем снизит линию Carrier Detect, что приведет к отправке отчета о завершении файла ядра и передаваемого сигнала SIGHUP.

WINCH не подходит для "изменения окна". Он отправляется процессу, если его управляющий терминал изменяет размер. По понятным причинам терминалы, которые могут изменять размер, обычно представляют собой псевдотерминалы, которые в конечном счете представлены терминальным эмулятором, работающим в среде окон (например, xterm).

Ответ 3

Попробуйте kill -l и найдите ответ самостоятельно:

1)  SIGHUP       2)  SIGINT       3)  SIGQUIT      4)  SIGILL       5)  SIGTRAP
6)  SIGABRT      7)  SIGBUS       8)  SIGFPE       9)  SIGKILL      10) SIGUSR1
11) SIGSEGV      12) SIGUSR2      13) SIGPIPE      14) SIGALRM      15) SIGTERM
16) SIGSTKFLT    17) SIGCHLD      18) SIGCONT      19) SIGSTOP      20) SIGTSTP
21) SIGTTIN      22) SIGTTOU      23) SIGURG       24) SIGXCPU      25) SIGXFSZ
26) SIGVTALRM    27) SIGPROF      28) SIGWINCH     29) SIGIO        30) SIGPWR
31) SIGSYS       34) SIGRTMIN     35) SIGRTMIN+1   36) SIGRTMIN+2   37) SIGRTMIN+3
38) SIGRTMIN+4   39) SIGRTMIN+5   40) SIGRTMIN+6   41) SIGRTMIN+7   42) SIGRTMIN+8
43) SIGRTMIN+9   44) SIGRTMIN+10  45) SIGRTMIN+11  46) SIGRTMIN+12  47) SIGRTMIN+13
48) SIGRTMIN+14  49) SIGRTMIN+15  50) SIGRTMAX-14  51) SIGRTMAX-13  52) SIGRTMAX-12
53) SIGRTMAX-11  54) SIGRTMAX-10  55) SIGRTMAX-9   56) SIGRTMAX-8   57) SIGRTMAX-7
58) SIGRTMAX-6   59) SIGRTMAX-5   60) SIGRTMAX-4   61) SIGRTMAX-3   62) SIGRTMAX-2
63) SIGRTMAX-1   64) SIGRTMAX

Ответ 4

Поскольку имена сигналов стандартизируются (POSIX). Вы можете написать свой собственный исполняемый файл kill-типа, чтобы взять -UPGRADE, если хотите, и доставить сигнал USR1, но стандартный kill, который поставляется с UNIX, не узнает его.

В качестве альтернативы вы можете создать псевдоним, функцию или оболочку script для выполнения перевода для вас, например, с помощью псевдонима bash:

alias upgrade='kill -USR1'

Файл заголовка signal.h сопоставляет имена сигналов с их фактическими значениями, зависящими от реализации.

В терминах WINCH я считаю это немного мерзостью. Это сигнал, который доставляется приложениям при изменении размера окна (особенно когда изменяется окно их управляющего терминала).

Использование этого для изящного закрытия рабочих потоков не является хорошей идеей, если вы не можете гарантировать, что процесс никогда не будет работать в терминале. Я знаю, что был бы очень миф, если бы я запускал приложение, и он решил отменить всю работу в полете только потому, что я максимизировал окно: -)

Ответ 5

На платформах, совместимых с POSIX, SIGUSR1 и SIGUSR2 - это сигналы, посылаемые процессу для указания пользовательских условий. Символьные константы для них определены в файле заголовка signal.h. Символические имена сигналов используются, поскольку номера сигналов могут различаться на разных платформах.

SIG является общим префиксом для имен сигналов. USR является аббревиатурой для пользовательских.

Ответ 6

Имена сигналов начинаются с более ранних времен, чем Posix.

Я хочу поговорить о SIG ** IOT **. В то время, когда использовались мейнфреймы DEC PDP, используемый процессор имел специальную инструкцию IOT (Trap I/O Trap), которая часто использовалась для кратковременного сбоя системы - как правило, для ее перезагрузки (в серверах реального времени). Этот метод использовал все ядро ​​вместе с драйверами устройств и привилегированные процессы (написанные на ассемблере). Даже сегодня есть процессоры, которые все еще имеют эту инструкцию IOT.

Итак, когда ядро ​​испытывает выполнение инструкции IOT в непривилегированном домене, он вызывает SIGIOT для затронутого процесса.