web-dev-qa-db-ja.com

SIGTERMは、SIGTERM、SIGQUIT、SIGKILLなどの他の終了シグナルとどのように関連していますか?

POSIXシステムでは、終了信号は通常、次の順序になっています(多くのMANページおよびPOSIX仕様による):

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

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

  3. SIGKILL-最も強制的な要求。プロセスは何もするように求められませんが、システムはそれが好きかどうかにかかわらず、プロセスをクリーンアップします。ほとんどの場合、コアダンプが書き込まれます。

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

UPDATE:

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

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

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

そして、それはSIGQUITについて言います:

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

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

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

91
Mecki

SIGTERMおよびSIGKILLは、一般的な目的の「このプロセスを終了する」要求を対象としています。 SIGTERM(デフォルト)およびSIGKILL(常に)によりプロセスが終了します。 SIGTERMはプロセスによってキャッチされる場合があり(たとえば、必要に応じて独自のクリーンアップを実行できるようにするため)、完全に無視されることさえあります。しかし、SIGKILLはキャッチまたは無視できません。

SIGINTおよびSIGQUITは、特に端末からの要求を対象としています。特定の入力文字を割り当てて、これらの信号を生成できます(端末制御設定に応じて)。 SIGINTのデフォルトアクションは、SIGTERMのデフォルトアクションおよびSIGKILLの変更不可能なアクションと同じ種類のプロセス終了です。 SIGQUITのデフォルトアクションもプロセスの終了ですが、コアダンプの生成など、追加の実装定義のアクションが発生する場合があります。必要に応じて、プロセスでキャッチまたは無視できます。

あなたが言うように、SIGHUPは、終端信号そのものではなく、端末接続が失われたことを示すことを目的としています。ただし、SIGHUPのデフォルトのアクション(プロセスがキャッチまたは無視しない場合)は、SIGTERMなどと同じ方法でプロセスを終了することです。

[〜#〜] posix [〜#〜] の定義に signal.h さまざまなシグナルとそれらのデフォルトのアクションと目的をリストします。 General Terminal Interface の章には、ターミナル関連のシグナルに関する詳細が含まれています。

74

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

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

Googleで sigint vs sigterm をすばやく検索した後、キーボードショートカットによって開始されたか、killの明示的な呼び出しによって開始されたかは、2つの間の唯一の意図した違いのようです。

その結果、たとえば、sigintをインターセプトし、キーボードショートカットによって送信された可能性があることを認識して、特別な操作を行うことができます。おそらく、死ぬのではなく、画面または何かを更新します(人々が期待するように、推奨されません^Cはプログラムを強制終了するための例です。

また、^\は、sigquitを送信する必要があります。とても便利そうです。

7
Jonathan

man 7 signal

これは Linux man-pages project の便利な非規範的なマンページであり、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にはアクションCoreおよびSIGINT Termがあるため、SIGQUITからのSIGQUIT。

アクションは同じドキュメントに記載されています。

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.

両方のアクションがTermであり、両方ともキャッチできるので、カーネルの観点からSIGTERMとSIGINTの違いを見ることはできません。これは単なる「一般的な使用規則の違い」のようです。

  • 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

その最小の具体例 です。

カーネルによって送信された信号

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

つまり、SIGINTは実際にはCtrl-C割り込みを示すためのものであり、SIGTERMは一般的な端末シグナルです。シグナルが「より強力」であるという概念はありませんが、ブロックまたは処理できないシグナルがあるという唯一の例外があります(マニュアルページによると、SIGKILLおよびSIGSTOP)。

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

3
DarkDust

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