Як SIGINT ставиться до інших сигналів припинення, таких як SIGTERM, SIGQUIT та SIGKILL?


103

У системах POSIX сигнали завершення зазвичай мають такий порядок (згідно багатьох сторінок MAN та специфікації POSIX):

  1. SIGTERM - ввічливо попросіть процес припинити. Він закінчується граціозно, очищаючи всі ресурси (файли, розетки, дочірні процеси тощо), видаляючи тимчасові файли тощо.

  2. SIGQUIT - більш сильний запит. Він припиняє недоброзичливе, все ще очищення ресурсів, які абсолютно потребують очищення, але, можливо, не видаляє тимчасові файли, можливо, де-небудь записувати інформацію про налагодження; в якійсь системі також буде записано основний дамп (незалежно від того, подано сигнал додатком чи ні).

  3. SIGKILL - найсильніший запит. Процес навіть не просять нічого робити, але система очистить процес, хоч він це чи ні. Швидше за все, написано основний дамп.

Як SIGINT вписується у цю картину? Процес CLI зазвичай закінчується SIGINT, коли користувач потрапляє на CRTL + C, проте фоновий процес також може бути припинений SIGINT за допомогою утиліти KILL. Те, що я не бачу у специфікаціях або файлах заголовка, це якщо SIGINT більш-менш сильний, ніж SIGTERM або якщо взагалі є різниця між SIGINT та SIGTERM.

ОНОВЛЕННЯ:

Найкращий опис сигналів про припинення, які я знайшов поки що, знаходиться в Документації GNU LibC . Це дуже добре пояснює, що між SIGTERM та SIGQUIT існує намічена різниця.

Це говорить про SIGTERM:

Це звичайний спосіб ввічливо попросити програму припинити.

І це говорить про SIGQUIT:

[...] і виробляє дамп ядра, коли він завершує процес, як і сигнал про помилку програми. Ви можете вважати це як стан програмної помилки, «виявлений» користувачем. [...] Окремі види очищення найкраще опускати під час обробки SIGQUIT. Наприклад, якщо програма створює тимчасові файли, вона повинна обробляти інші запити на припинення, видаляючи тимчасові файли. Але для SIGQUIT краще не видаляти їх, щоб користувач міг їх вивчити спільно з основним дамп.

І SIGHUP також пояснюється досить добре. SIGHUP - це насправді не сигнал про припинення, він просто означає, що "з'єднання" з користувачем було втрачено, тому додаток не може очікувати, що користувач прочитає будь-який поданий вихід (наприклад, вихід stdout / stderr), і немає ніякого входу, якого слід очікувати від користувач більше. Для більшості програм це означає, що вони краще вийдуть. Теоретично додаток також може вирішити, що він переходить у демон-режим, коли приймається SIGHUP і тепер працює як фоновий процес, записуючи вихід у налаштований файл журналу. Для більшості демонів, які вже працюють у фоновому режимі, SIGHUP зазвичай означає, що вони повинні переглянути свої конфігураційні файли, тому ви надсилаєте їх фоновим процесам після редагування конфігураційних файлів.

Однак на цій сторінці немає жодного корисного пояснення SIGINT, крім того, що воно надсилається CRTL + C. Чи є якась причина, чому можна було б поводитися з SIGINT інакше, ніж SIGTERM? Якщо так, яка це причина і як би поводження було б різним?


1
Гарне питання. Я підозрюю, що у відповіді будуть задіяні деякі історичні твори Unix.
Алекс Б

Я знаю, що це питання давнє, але якщо хтось прийшов сюди для широкого списку сигналів для вашої (Linux) ОС, їх можна знайти, ввівши sudo fuser -lкомандний рядок. Для мене це підводить:HUP INT QUIT ILL TRAP ABRT IOT BUS FPE KILL USR1 SEGV USR2 PIPE ALRM TERM STKFLT CHLD CONT STOP TSTP TTIN TTOU URG XCPU XFSZ VTALRM PROF WINCH IO PWR SYS UNUSED
Нік Булл

3
Спробуйте також kill -lпереглянути список сигналів.
AAAfarmclub

Відповіді:


88

SIGTERM і SIGKILL призначені для загальних цілей запитів "припинити цей процес". SIGTERM (за замовчуванням) та SIGKILL (завжди) спричинить припинення процесу. SIGTERM може потрапити в процес (наприклад, щоб він міг зробити власне очищення, якщо захоче), або навіть повністю ігнорувати; але SIGKILL не можна зловити або проігнорувати

SIGINT і SIGQUIT призначені спеціально для запитів від терміналу: окремі вхідні символи можуть бути призначені для генерування цих сигналів (залежно від параметрів управління терміналу). Дія за замовчуванням для SIGINT - це такий самий вид припинення процесу, що і дія за замовчуванням для SIGTERM та незмінна дія для SIGKILL; дією за замовчуванням для SIGQUIT також є завершення процесу, але можуть виникати додаткові дії, визначені реалізацією, такі як генерація дампів ядра. Якщо це потрібно, процес може бути спійманий або проігнорований.

Як ви говорите, SIGHUP має на меті вказати на те, що термінальне з'єднання втрачено, а не як сигнал припинення як такий. Але, знову ж таки, за замовчуванням для SIGHUP (якщо процес не вловлює або ігнорує) - це припинити процес так само, як SIGTERM тощо.

У визначеннях POSIX є таблиця, в signal.hякій перераховані різні сигнали та їх дії та цілі за замовчуванням, а глава Загальний термінальний інтерфейс містить значно більше деталей щодо сигналів, пов'язаних з терміналом.


10
Це головний момент: під час роботи програми SIGINT та SIGQUIT можна генерувати з терміналу за допомогою окремих символів. Інші сигнали повинні якось генеруватися іншою програмою (наприклад, командою kill). SIGINT менш жорстокий, ніж SIGQUIT; останній виробляє основний відвал. SIGKILL не може бути захоплений. SIGHUP генерується, якщо ваше з'єднання зависне (вікно закривається тощо). Отже, всі вони мають різні значення.
Джонатан Леффлер

TTY Demystified має деяку легкозасвоювану інформацію про те, як сигнали взаємодіють із підсистемою tty ядра. Додає якийсь контекст до вашої відповіді.
Даніель Наслунд

2
Схоже, характеристики не дуже точні, але я розумію, що SIgint просить програму припинити її поточну дію, а не обов'язково кидати. Для програми, розробленої лише для однієї дії за цикл, яка передбачає вихід, але для інтерактивної програми, яка має певний цикл для читання-eval-print, це може означати відмову від поточного eval та повернення до читання даних користувача. Я думаю, що менше робить це на підписі.
bdsl

Який сигнал надсилається під час перезавантаження?
Дан Даскалеску

10

Як зауважив DarkDust, багато сигналів мають однакові результати, але процеси можуть приєднувати до них різні дії, розрізняючи спосіб генерування кожного сигналу. Переглядаючи вихідний код ядра FreeBSD (kern_sig.c), я бачу, що два сигнали обробляються однаково, вони завершують процес і доставляються в будь-який потік.

SA_KILL|SA_PROC,             /* SIGINT */
SA_KILL|SA_PROC,             /* SIGTERM */

9

man 7 signal

Це зручна ненормативна сторінка проекту чоловічих сторінок Linux, яку ви хочете часто шукати для інформації про сигнали Linux.

Версія 3.22 згадує такі цікаві речі, як:

Сигнали SIGKILL і SIGSTOP не можуть бути захоплені, заблоковані або проігноровані.

і містить таблицю:

Signal     Value     Action   Comment
----------------------------------------------------------------------
SIGHUP        1       Term    Hangup detected on controlling terminal
                              or death of controlling process
SIGINT        2       Term    Interrupt from keyboard
SIGQUIT       3       Core    Quit from keyboard
SIGILL        4       Core    Illegal Instruction
SIGABRT       6       Core    Abort signal from abort(3)
SIGFPE        8       Core    Floating point exception
SIGKILL       9       Term    Kill signal
SIGSEGV      11       Core    Invalid memory reference
SIGPIPE      13       Term    Broken pipe: write to pipe with no
                              readers
SIGALRM      14       Term    Timer signal from alarm(2)
SIGTERM      15       Term    Termination signal
SIGUSR1   30,10,16    Term    User-defined signal 1
SIGUSR2   31,12,17    Term    User-defined signal 2
SIGCHLD   20,17,18    Ign     Child stopped or terminated
SIGCONT   19,18,25    Cont    Continue if stopped
SIGSTOP   17,19,23    Stop    Stop process
SIGTSTP   18,20,24    Stop    Stop typed at tty
SIGTTIN   21,21,26    Stop    tty input for background process
SIGTTOU   22,22,27    Stop    tty output for background process

який підсумовує сигнал, Actionякий відрізняє, наприклад, SIGQUIT від SIGQUIT, оскільки SIGQUIT має дію Coreта SIGINT Term.

Дії задокументовані в одному документі:

The entries in the "Action" column of the tables below specify the default disposition for each signal, as follows:

Term   Default action is to terminate the process.

Ign    Default action is to ignore the signal.
Core   Default action is to terminate the process and dump core (see core(5)).
Stop   Default action is to stop the process.
Cont   Default action is to continue the process if it is currently stopped.

Я не бачу різниці між SIGTERM та SIGINT з точки зору ядра, оскільки вони мають дію, Termі обидва можуть бути спіймані. Здається, це лише "загальне розмежування умов використання":

  • SIGINT - це те, що відбувається, коли ви робите CTRL-C з терміналу
  • SIGTERM - сигнал за замовчуванням, який надсилає повідомлення kill

Деякі сигнали - ANSI C, а інші - ні

Суттєва різниця полягає в тому, що:

  • SIGINT і SIGTERM - ANSI C, таким чином, більш портативні
  • SIGQUIT і SIGKILL не є

Вони описані в розділі "7.14 Поводження з сигналом" проекту C99 N1256 :

  • SIGINT отримання інтерактивного сигналу уваги
  • SIGTERM запит на припинення, надісланий програмі

що робить SIGINT хорошим кандидатом для інтерактивного Ctrl + C.

POSIX 7

POSIX 7 документує сигнали із signal.hзаголовком: https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/signal.h.html

На цій сторінці також є наступна таблиця інтересів, в якій згадуються деякі речі, які ми вже бачили man 7 signal:

Signal    Default Action   Description
SIGABRT   A                Process abort signal.
SIGALRM   T                Alarm clock.
SIGBUS    A                Access to an undefined portion of a memory object.
SIGCHLD   I                Child process terminated, stopped,
SIGCONT   C                Continue executing, if stopped.
SIGFPE    A                Erroneous arithmetic operation.
SIGHUP    T                Hangup.
SIGILL    A                Illegal instruction.
SIGINT    T                Terminal interrupt signal.
SIGKILL   T                Kill (cannot be caught or ignored).
SIGPIPE   T                Write on a pipe with no one to read it.
SIGQUIT   A                Terminal quit signal.
SIGSEGV   A                Invalid memory reference.
SIGSTOP   S                Stop executing (cannot be caught or ignored).
SIGTERM   T                Termination signal.
SIGTSTP   S                Terminal stop signal.
SIGTTIN   S                Background process attempting read.
SIGTTOU   S                Background process attempting write.
SIGUSR1   T                User-defined signal 1.
SIGUSR2   T                User-defined signal 2.
SIGTRAP   A                Trace/breakpoint trap.
SIGURG    I                High bandwidth data is available at a socket.
SIGXCPU   A                CPU time limit exceeded.
SIGXFSZ   A                File size limit exceeded.

BusyBox init

Команда за замовчуванням 1.29.2 BusyBox rebootнадсилає SIGTERM до процесів, спить на секунду, а потім надсилає SIGKILL. Це, мабуть, є загальною умовою у різних дистрибуціях.

Коли ви вимикаєте систему BusyBox за допомогою:

reboot

він посилає сигнал до процесу init.

Потім обробник сигналу init закінчує дзвінок:

static void run_shutdown_and_kill_processes(void)
{
    /* Run everything to be run at "shutdown".  This is done _prior_
     * to killing everything, in case people wish to use scripts to
     * shut things down gracefully... */
    run_actions(SHUTDOWN);

    message(L_CONSOLE | L_LOG, "The system is going down NOW!");

    /* Send signals to every process _except_ pid 1 */
    kill(-1, SIGTERM);
    message(L_CONSOLE, "Sent SIG%s to all processes", "TERM");
    sync();
    sleep(1);

    kill(-1, SIGKILL);
    message(L_CONSOLE, "Sent SIG%s to all processes", "KILL");
    sync();
    /*sleep(1); - callers take care about making a pause */
}

яка друкує до терміналу:

The system is going down NOW!
Sent SIGTERM to all processes
Sent SIGKILL to all processes

Ось мінімальний конкретний приклад цього .

Сигнали, що надсилаються ядром


8

Після швидкого пошуку в Google Sigintm та Sigterm , схоже, єдиною наміченою різницею є те, чи це було ініційовано комбінацією клавіш або явним викликом до kill.

Як результат, ви могли, наприклад, перехопити підпис та зробити щось особливе з ним, знаючи, що воно, ймовірно, надіслане комбінацією клавіш. Можливо, оновіть екран чи щось, а не вмирайте (не рекомендується, оскільки люди розраховують ^Cвбити програму, лише приклад).

Я також дізнався, що ^\слід надсилати сигвіт, який я можу почати використовувати сам. Виглядає дуже корисно.


3

За допомогою kill(як системного виклику, так і утиліти "ви можете надіслати майже будь-який сигнал до будь-якого процесу, якщо ви отримали дозвіл. Процес не може визначити, як сигнал ожив і хто його надіслав.

При цьому, SIGINT дійсно призначений для сигналізації переривання Ctrl-C, тоді як SIGTERM є загальним термінальним сигналом. Немає поняття, щоб сигнал був "більш сильним", за винятком лише того, що існують сигнали, які неможливо заблокувати або обробити (SIGKILL і SIGSTOP, згідно зі сторінкою man).

Сигнал може бути "більш сильним", ніж інший сигнал щодо того, як процес прийому обробляє сигнал (і які дії за замовчуванням для цього сигналу). Наприклад, за замовчуванням як SIGTERM, так і SIGINT призводять до припинення. Але якщо ви проігноруєте SIGTERM, він не припинить ваш процес, тоді як SIGINT все-таки є.


0

За винятком кількох сигналів, обробники сигналів можуть вловлювати різні сигнали, або поведінка за замовчуванням після отримання сигналу може бути змінена. Детальну інформацію див. На signal(7)сторінці чоловіка.


Так, але якщо я не знаю "значення" синглану, ловити сигнал безглуздо, тому що я не знаю, що робити у своїй заяві. GNU C, наприклад, пояснює різницю між SIGQUIT і SIGTERM. Але це дає мало інформації про SIGINT: gnu.org/s/libc/manual/html_node/Termina-Signals.html
Mecki

" SIGINTСигнал (" переривання програми ") надсилається, коли користувач вводить символ INTR (як правило C-c)." "SIGINT 2 Термін переривання з клавіатури" Ви натискаєте Ctrl-C, SIGINTвідправляється. Процес зазвичай гине. Що більше подарувати?
Ігнасіо Васкес-Абрамс

Потенційно може бути опис наміру, який програміст повинен припустити, що користувач матиме, коли він натисне ctrl-c, тобто семантику повідомлення. Як приклад, специфікація HTTP пояснює, що коли користувач надсилає GET-запит, сервер не повинен вважати, що вони бажають, щоб він робив що-небудь, крім повернення відповіді.
bdsl
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.