web-dev-qa-db-ja.com

さまざまな信号が送信される原因は何ですか?

プロセスが受信できるすべてのシグナルに少し混乱することがあります。私が理解しているように、プロセスにはこれらのシグナルごとにデフォルトのハンドラー(signal disposition)がありますが、-を呼び出すことで独自のハンドラーを提供できます sigaction()

だからここに私の質問です:各信号が送信される原因は何ですか? -sパラメータからkillを介して実行中のプロセスに手動で信号を送信できることを理解していますが、naturalとはこれらの信号が送信される状況は?たとえば、SIGINTはいつ送信されますか?

また、扱える信号に制限はありますか? SIGSEGV信号さえ処理して、制御をアプリケーションに戻すことができますか?

29
Nathan Osman

プロセスが kill(2) を呼び出すことに加えて、いくつかの signals は、さまざまな状況でカーネル(またはプロセス自体)によって送信されます。

  • 端末ドライバは、さまざまなイベントに対応する信号を送信します。
    • キープレス通知: SIGINT (メインループに戻ってください) Ctrl+CSIGQUIT (すぐに終了してください) Ctrl+\SIGTSTP (一時停止してください) Ctrl+Z。キーは stty コマンドで変更できます。
    • SIGTTIN および SIGTTOU は、バックグラウンドプロセスが制御端末に対して読み取りまたは書き込みを行おうとすると送信されます。
    • SIGWINCH は、ターミナルウィンドウのサイズが変更されたことを通知するために送信されます。
    • SIGHUP は、端末が消えたことを通知するために送信されます(歴史的には、モデムにhungup、今日では通常、ターミナルエミュレータウィンドウを閉じているためです)。
  • 一部のプロセッサトラップは信号を生成できます。詳細はアーキテクチャとシステムに依存します。ここに典型的な例があります:
    • SIGBUS アライメントされていないアクセスメモリの場合。
    • SIGSEGV マップされていないページへのアクセス用。
    • SIGILL 不正な命令(不正なオペコード)の場合
    • SIGFPE 引数が不正な浮動小数点命令の場合(例:sqrt(-1))。
  • いくつかのシグナルが、何らかのシステムイベントが発生したことをターゲットプロセスに通知します。
    • SIGALRM プロセスによって設定されたタイマーが期限切れになったことを通知します。タイマーは alarmsetitimer などで設定できます。
    • SIGCHLD は、その子の1つが死亡したことをプロセスに通知します。
    • SIGPIPE は、読み取り側が閉じているときにプロセスがパイプに書き込もうとすると生成されます(foo | barbarを実行すると、fooSIGPIPEによって強制終了されるという考えです) 。
    • SIGPOLLSIGIOとも呼ばれます)は、ポーリング可能なイベントが発生したことをプロセスに通知します。 POSIXは、I_SETSIGioctl によって登録されたポーリング可能なイベントを指定します。多くのシステムでは、O_ASYNCfcntl フラグで設定されたファイル記述子でポーリング可能なイベントを許可しています。関連する信号は SIGURG で、これはデバイスの緊急データを通知します(I_SETSIGioctl を介して登録)または socket
    • 一部のシステムでは、 [〜#〜] ups [〜#〜] が停電が差し迫っていることを通知すると、 SIGPWR がすべてのプロセスに送信されます。

これらのリストは完全ではありません。標準信号は signal.h で定義されています。

ほとんどのシグナルは、アプリケーションでキャッチおよび処理(または無視)できます。キャッチできない2つのポータブル信号は SIGKILL (ただ死ぬ)と STOP (実行を停止)だけです。

SIGSEGVsegmentation fault )とその従兄弟 SIGBUSbus error )は捕捉できますが、それは悪い考えですあなたが本当に何をしているかを知らない限り。それらをキャッチするための一般的なアプリケーションは、スタックトレースまたはその他のデバッグ情報を出力することです。より高度なアプリケーションは、ある種のインプロセスメモリ管理を実装すること、または仮想マシンエンジンで不正な命令をトラップすることです。

最後に、シグナルではないものについて触れておきます。押すと Ctrl+D 端末から入力を読み込んでいるプログラムの行の先頭で、これはプログラムに入力ファイルの終わりに達したことを伝えます。これはシグナルではなく、入出力APIを介して送信されます。お気に入り Ctrl+C と友達、キーはsttyで設定できます。

最初に2番目の質問に答えるには:SIGSTOPSIGKILLをアプリケーションでキャッチすることはできませんが、SIGSEGVであっても他のすべてのシグナルはキャッチできます。このプロパティはデバッグに役立ちます。たとえば、適切なライブラリサポートがあれば、SIGSEGVをリッスンしてスタックバックトレースを生成し、segfaultが発生した場所だけを表示できます。

Linuxのコマンドラインから_man 7 signal_と入力すると、各信号の動作に関する公式のWord(Linuxの場合はとにかく)を利用できます。 http://linux.die.net/man/7/signal にも同じ情報がありますが、表は読みにくくなっています。

ただし、信号に関するいくつかの経験がないと、信号が実際に何をしているのかを簡単な説明から知るのは難しいので、ここに私の解釈を示します。

キーボードからトリガー

  • SIGINTは、_CTRL+C_を押すと発生します。
  • SIGQUITは_CTRL+\_によってトリガーされ、コアをダンプします。
  • SIGTSTPは、_CTRL+Z_を押すとプログラムを中断します。 SIGSTOPとは異なり、キャッチ可能です。これにより、viのようなプログラムに、端末を一時停止する前に安全な状態にリセットする機会が与えられます。

端末の相互作用

  • SIGHUP( "hangup")は、プログラムの実行中にxtermを閉じる(またはターミナルを切断する)とどうなるかです。
  • SIGTTINおよびSIGTTOUは、プログラムがバックグラウンドで実行されているときに端末からの読み取りまたは端末への書き込みを試みると、プログラムを一時停止します。 SIGTTOUが発生するには、プログラムがデフォルトのstdoutだけでなく、_/dev/tty_に書き込む必要があると思います。

CPU例外によってトリガーされました

これらはあなたのプログラムが何か間違ったことをしようとしたことを意味します。

  • SIGILLは、不正または不明なプロセッサ命令を意味します。これは、たとえば、プロセッサI/Oポートに直接アクセスしようとした場合に発生する可能性があります。
  • SIGFPEは、ハードウェア数学エラーがあったことを意味します。おそらくプログラムはゼロで除算しようとしました。
  • SIGSEGVは、プログラムがマップされていないメモリ領域にアクセスしようとしたことを意味します。
  • SIGBUSは、プログラムが他の方法でメモリに誤ってアクセスしたことを意味します。この要約の詳細には触れません。

プロセスの相互作用

  • SIGPIPEは、パイプのリーダーがパイプの終わりを閉じた後にパイプに書き込もうとすると発生します。 _man 7 pipe_を参照してください。
  • SIGCHLDは、作成した子プロセスが終了するか、(SIGSTOPなどによって)中断されたときに発生します。

自己通知に役立ちます

  • SIGABRTは通常、プログラムがabort()関数を呼び出すことで発生し、デフォルトでコアダンプが発生します。 「パニックボタン」のようなものです。
  • SIGALRMalarm()システムコールが原因で発生します。これにより、カーネルは指定された秒数後にSIGALRMをプログラムに配信します。 _man 2 alarm_および_man 2 sleep_を参照してください。
  • _SIGUSR1_と_SIGUSR2_は、プログラムの好みに応じて使用されます。これらは、プロセス間のシグナリングに役立ちます。

管理者から送信されました

これらの信号は通常、コマンドプロンプトからkillコマンド、またはfgまたはbgの場合はSIGCONTを介して送信されます。

  • SIGKILLおよびSIGSTOPは、ブロックできない信号です。最初のものは常にプロセスを即座に終了します。 2番目はプロセスを中断します。
  • SIGCONTは、中断されたプロセスを再開します。
  • SIGTERMSIGKILLのキャッチ可能なバージョンです。
19
Jander