SIGINTは、SIGTERM、SIGQUIT、SIGKILLなどの他の終了信号とどのように関連していますか?


103

POSIXシステムでは、終了信号は通常次の順序になります(多くのMANページとPOSIX仕様による)。

  1. SIGTERM-プロセスに終了を丁寧に要求します。正常に終了し、すべてのリソース(ファイル、ソケット、子プロセスなど)をクリーンアップし、一時ファイルを削除します。

  2. SIGQUIT-より強力なリクエスト。クリーンアップが絶対に必要なリソースをクリーンアップしますが、一時ファイルは削除せず、デバッグ情報をどこかに書き込む可能性があります。一部のシステムでは、コアダンプが書き込まれます(信号がアプリによってキャッチされるかどうかに関係なく)。

  3. SIGKILL-最も強力なリクエスト。プロセスは何もするように要求されることさえありませんが、システムはそれが好きかどうかに関わらず、プロセスをクリーンアップします。おそらくコアダンプが書き込まれます。

SIGINTはどのようにその画像に適合しますか?CLIプロセスは通常、ユーザーがCRTL + Cを押すとSIGINTによって終了しますが、バックグラウンドプロセスは、KILLユーティリティを使用してSIGINTによって終了することもできます。仕様またはヘッダーファイルで確認できないのは、SIGINTがSIGTERMよりも強いか弱いか、またはSIGINTとSIGTERMの間にまったく違いがあるかどうかです。

更新:

私がこれまでに見つけた終了信号の最も良い説明は、GNU LibC Documentationにあります。これは、SIGTERMとSIGQUITの間に意図された違いがあることを非常によく説明しています。

それはSIGTERMについて言います:

これは、プログラムに終了を丁寧に要求する通常の方法です。

そしてそれはSIGQUITについて述べています:

[...]プログラムエラー信号のように、プロセスを終了するとコアダンプを生成します。これは、ユーザーによって「検出」されたプログラムエラー状態と考えることができます。[...]特定の種類のクリーンアップは、SIGQUITの処理では省略されるのが最適です。たとえば、プログラムが一時ファイルを作成する場合、一時ファイルを削除することにより、他の終了要求を処理する必要があります。ただし、SIGQUITはそれらを削除しない方がよいため、ユーザーはコアダンプと組み合わせてそれらを調べることができます。

そしてSIGHUPも十分に説明されています。SIGHUPは実際には終了信号ではなく、単にユーザーへの「接続」が失われたことを意味するため、アプリはユーザーがそれ以上の出力(例:stdout / stderr出力)を読み取ることを期待できず、期待される入力がありません。もはやユーザー。ほとんどのアプリでは、終了することを意味します。理論的には、SIGHUPを受信すると、アプリがデーモンモードになり、バックグラウンドプロセスとして実行され、設定されたログファイルに出力が書き込まれるようにアプリを決定することもできます。すでにバックグラウンドで実行されているほとんどのデーモンの場合、SIGHUPは通常、構成ファイルを再検査する必要があることを意味するため、構成ファイルを編集した後、デーモンをバックグラウンドプロセスに送信します。

ただし、このページには、CRTL + Cから送信されるSIGINTに関する有用な説明はありません。SIGINTをSIGTERMとは異なる方法で処理する理由はありますか?もしそうなら、これはどのような理由であり、処理はどのように異なるのでしょうか?


1
良い質問。歴史的なUnixの残骸のいくつかが答えに関係しているのではないかと思います。
Alex B

私はこの質問が古いことを知っていますが、誰かがあなたの(Linux)OS用のシグナルの広範なリストを求めてここに来た場合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 2016

回答:


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サブシステムとどのように相互作用するかについて、簡単に消化できる情報がいくつかあります。回答にコンテキストを追加します。
DanielNäslund、2012年

1
仕様はあまり正確ではないようですが、私の理解では、SIgintはプログラムに現在のアクションを停止するように求めています。必ずしも終了する必要はありません。設計されたプログラムの場合、実行を1回実行するだけで終了を意味しますが、ある種のread-eval-printループがあるインタラクティブプログラムの場合、現在のevalをあきらめて、ユーザー入力の読み取りに戻る可能性があります。sigintの場合はそれが少ないと思います。
BDSL

再起動中に送信される信号は何ですか?
Dan Dascalescu

10

DarkDustが指摘したように、多くの信号は同じ結果になりますが、プロセスは各信号の生成方法を区別することにより、それらに異なるアクションをアタッチできます。FreeBSDカーネルソースコード(kern_sig.c)を見ると、2つの信号が同じ方法で処理され、プロセスを終了し、任意のスレッドに配信されることがわかります。

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

ActionSIGQUITにはaction CoreとSIGINT があるため、たとえばSIGQUITとSIGQUITを区別する信号を要約し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は

それらは、C99ドラフトN1256の「7.14信号処理」セクションで説明されています

  • インタラクティブアテンションシグナルの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

BusyBoxの1.29.2デフォルトrebootコマンドは、SIGTERMをプロセスに送信し、1秒間スリープしてから、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でsigintとsigtermをすばやく検索したところ、両者の違いは、キーボードショートカットによって開始されたか、への明示的な呼び出しによって開始されたかだけが異なるようkillです。

その結果、たとえばsigintをインターセプトして、キーボードショートカットによって送信された可能性が高いことを知りながら、sigintで何か特別なことを行うことができます。おそらく、死ぬのではなく、画面または何かをリフレッシュします(人々^Cはプログラムを強制終了することを期待しているため、お勧めできません)。

また^\、自分が使い始める可能性があるsigquitを送信する必要があることも学びました。とても便利に見えます。


3

kill(システムコールとユーティリティの両方を使用すると、アクセス許可があれば、ほとんどすべてのシグナルを任意のプロセスに送信できます。プロセスは、シグナルがどのように発生したか、誰が送信したかを区別できません。

そうは言っても、SIGINTは実際にはCtrl-C割り込みを信号として送ることを目的としていますが、SIGTERMは一般的なターミナル信号です。シグナルが「より強力」であるという概念はありませんが、ブロックまたは処理できないシグナルがあることだけは例外です(SIGKILLおよびSIGSTOP、manページによると)。

シグナルは、受信プロセスがシグナルを処理する方法(およびそのシグナルのデフォルトのアクション)に関して、別のシグナルよりも「強力」にすることができます。たとえば、デフォルトでは、SIGTERMとSIGINTの両方が終了します。ただし、SIGTERMを無視すると、プロセスは終了しませんが、SIGINTは終了します。


0

いくつかの信号を除いて、信号ハンドラーはさまざまな信号をキャッチできます。または、信号の受信時のデフォルトの動作を変更できます。詳細については、signal(7)manページを参照してください。


はい。ただし、信号の「意味」がわからない場合、アプリケーションで何をすべきかわからないため、信号をキャッチしても意味がありません。GNU Cは、例えばSIGQUITとSIGTERMの違いを説明しています。しかし、それはSIGINTについて少し情報を提供します:gnu.org/s/libc/manual/html_node/Termination-Signals.htmlを
Mecki

SIGINT(「プログラム割り込み」)信号は、ユーザーがINTR文字(通常はC-c)を入力したときに送信されます。」「キーボードからのSIGINT 2項割り込み」Ctrl-Cを押すSIGINTと送信されます。プロセスは通常死にます。他に何を与える?
Ignacio Vazquez-Abrams

潜在的に、メッセージのセマンティクスであるctrl-cを押したときにプログラマーがユーザーが持っていると想定すべき意図の説明がある可能性があります。例として、HTTP仕様では、ユーザーがGET要求を送信するときに、サーバーが応答の送信以外のことを実行したいと想定してはならないことを明確にしています。
BDSL
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.