プロセスが受信できるすべてのシグナルに少し混乱することがあります。私が理解しているように、プロセスにはこれらのシグナルごとにデフォルトのハンドラー(signal disposition)がありますが、-を呼び出すことで独自のハンドラーを提供できます sigaction()
。
だからここに私の質問です:各信号が送信される原因は何ですか? -s
パラメータからkill
を介して実行中のプロセスに手動で信号を送信できることを理解していますが、naturalとはこれらの信号が送信される状況は?たとえば、SIGINT
はいつ送信されますか?
また、扱える信号に制限はありますか? SIGSEGV
信号さえ処理して、制御をアプリケーションに戻すことができますか?
プロセスが kill(2)
を呼び出すことに加えて、いくつかの signals は、さまざまな状況でカーネル(またはプロセス自体)によって送信されます。
SIGINT
(メインループに戻ってください) Ctrl+C、 SIGQUIT
(すぐに終了してください) Ctrl+\、 SIGTSTP
(一時停止してください) Ctrl+Z。キーは stty
コマンドで変更できます。SIGTTIN
および SIGTTOU
は、バックグラウンドプロセスが制御端末に対して読み取りまたは書き込みを行おうとすると送信されます。SIGWINCH
は、ターミナルウィンドウのサイズが変更されたことを通知するために送信されます。SIGHUP
は、端末が消えたことを通知するために送信されます(歴史的には、モデムにhungup、今日では通常、ターミナルエミュレータウィンドウを閉じているためです)。SIGALRM
プロセスによって設定されたタイマーが期限切れになったことを通知します。タイマーは alarm
、 setitimer
などで設定できます。SIGCHLD
は、その子の1つが死亡したことをプロセスに通知します。SIGPIPE
は、読み取り側が閉じているときにプロセスがパイプに書き込もうとすると生成されます(foo | bar
とbar
を実行すると、foo
がSIGPIPE
によって強制終了されるという考えです) 。SIGPOLL
(SIGIO
とも呼ばれます)は、ポーリング可能なイベントが発生したことをプロセスに通知します。 POSIXは、I_SETSIG
ioctl
によって登録されたポーリング可能なイベントを指定します。多くのシステムでは、O_ASYNC
fcntl
フラグで設定されたファイル記述子でポーリング可能なイベントを許可しています。関連する信号は SIGURG
で、これはデバイスの緊急データを通知します(I_SETSIG
ioctl
を介して登録)または socket 。SIGPWR
がすべてのプロセスに送信されます。これらのリストは完全ではありません。標準信号は signal.h
で定義されています。
ほとんどのシグナルは、アプリケーションでキャッチおよび処理(または無視)できます。キャッチできない2つのポータブル信号は SIGKILL
(ただ死ぬ)と STOP
(実行を停止)だけです。
SIGSEGV
( segmentation fault )とその従兄弟 SIGBUS
( bus error )は捕捉できますが、それは悪い考えですあなたが本当に何をしているかを知らない限り。それらをキャッチするための一般的なアプリケーションは、スタックトレースまたはその他のデバッグ情報を出力することです。より高度なアプリケーションは、ある種のインプロセスメモリ管理を実装すること、または仮想マシンエンジンで不正な命令をトラップすることです。
最後に、シグナルではないものについて触れておきます。押すと Ctrl+D 端末から入力を読み込んでいるプログラムの行の先頭で、これはプログラムに入力ファイルの終わりに達したことを伝えます。これはシグナルではなく、入出力APIを介して送信されます。お気に入り Ctrl+C と友達、キーはstty
で設定できます。
最初に2番目の質問に答えるには:SIGSTOP
とSIGKILL
をアプリケーションでキャッチすることはできませんが、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
_に書き込む必要があると思います。これらはあなたのプログラムが何か間違ったことをしようとしたことを意味します。
SIGILL
は、不正または不明なプロセッサ命令を意味します。これは、たとえば、プロセッサI/Oポートに直接アクセスしようとした場合に発生する可能性があります。SIGFPE
は、ハードウェア数学エラーがあったことを意味します。おそらくプログラムはゼロで除算しようとしました。SIGSEGV
は、プログラムがマップされていないメモリ領域にアクセスしようとしたことを意味します。SIGBUS
は、プログラムが他の方法でメモリに誤ってアクセスしたことを意味します。この要約の詳細には触れません。SIGPIPE
は、パイプのリーダーがパイプの終わりを閉じた後にパイプに書き込もうとすると発生します。 _man 7 pipe
_を参照してください。SIGCHLD
は、作成した子プロセスが終了するか、(SIGSTOP
などによって)中断されたときに発生します。SIGABRT
は通常、プログラムがabort()
関数を呼び出すことで発生し、デフォルトでコアダンプが発生します。 「パニックボタン」のようなものです。SIGALRM
はalarm()
システムコールが原因で発生します。これにより、カーネルは指定された秒数後にSIGALRM
をプログラムに配信します。 _man 2 alarm
_および_man 2 sleep
_を参照してください。SIGUSR1
_と_SIGUSR2
_は、プログラムの好みに応じて使用されます。これらは、プロセス間のシグナリングに役立ちます。これらの信号は通常、コマンドプロンプトからkill
コマンド、またはfg
またはbg
の場合はSIGCONT
を介して送信されます。
SIGKILL
およびSIGSTOP
は、ブロックできない信号です。最初のものは常にプロセスを即座に終了します。 2番目はプロセスを中断します。SIGCONT
は、中断されたプロセスを再開します。SIGTERM
はSIGKILL
のキャッチ可能なバージョンです。