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

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

時には、プロセスが受信できるすべての信号に対して少し混乱することがあります。私が理解したのは、プロセスには基本ハンドラ(信号処理)各信号に対して呼び出されますが、独自のハンドラを提供できます。sigaction()

私の質問は次のとおりです。各信号が送信される原因は何ですか?-sの引数を介して実行中のプロセスに手動でシグナルを送信できることを知っていますがkill自然これらの信号はどのような状況で送信されますか?たとえば、いつSIGINT出荷されますか?

また、どの信号を処理できるかについて制限がありますか?SIGSEGV信号を処理してアプリケーションに制御を返すことは可能ですか?

答え1

プロセスコールに加えてkill(2)、一部シグナルさまざまな状況でカーネル(または時にはプロセス自体)によって送信されます。

  • 端末ドライバは、様々なイベントに対応する信号を送信する。
    • キー押下通知: SIGINT(メインループに戻ります) On Ctrl+ CSIGQUIT(すぐに終了してください)on Ctrl+ \SIGTSTP(しばらくしてください)Ctrl+ Z。次のコマンドを使用してキーストロークを変更できますstty注文する。
    • SIGTTINそしてSIGTTOUバックグラウンド・プロセスが制御端末から読み書きするときに送信されます。
    • SIGWINCH端末ウィンドウのサイズが変更されたことを示す信号を送信します。
    • SIGHUP端末が消えたことを知らせます(歴史的にモデムが消えたため)。時間ウォン戻る(これは通常、端末エミュレータウィンドウを閉じたためです)。
  • 一部のプロセッサトラップは信号を生成できます。詳細はアーキテクチャとシステムによって異なります。以下は一般的な例です。
    • SIGBUSメモリへのソートされていないアクセスの場合。
    • SIGSEGVマップされていないページにアクセスするために使用されます。
    • SIGILL無効な命令(無効なオペコード)
    • SIGFPEパラメータが無効な浮動小数点コマンドの場合(例sqrt(-1):)
  • 多くの信号は、特定のシステムイベントが発生したことをターゲットプロセスに通知します。
    • SIGALRM設定されたタイマーの有効期限が切れたことをプロセスに通知します。タイマーは次のように設定できます。alarmsetitimer他の人。
    • SIGCHLD子プロセスの1つが終了したことをプロセスに通知します。
    • SIGPIPEfoo | bar読み取り側が閉じている間にプロセスがパイプに書き込もうとしたときに生成されます(実行して終了するとbar終了fooするという概念ですSIGPIPE)。
    • SIGPOLL(とも呼ばれるSIGIO)ポーリング可能なイベントが発生したことをプロセスに通知します。 POSIXは、以下を介して登録されたポーリング可能なイベントを指定します。I_SETSIG ioctl。多くのシステムでは、次のすべてのファイル記述子でポーリング可能なイベントを許可します。O_ASYNC fcntlバナー。関連信号はSIGURG、機器に緊急データを通知する(登録I_SETSIG ioctl) またはソケット
    • 一部のシステムではSIGPWRすべてのプロセスに転送されるときアップ停電が差し迫ったことを示します。

このリストは完全なものではありません。標準信号は次のように定義されます。signal.h

ほとんどの信号はアプリケーションによってキャプチャおよび処理(または無視)できます。キャプチャできない唯一のポータブル信号は2つでした。SIGKILL(ただ死ぬ)とSTOP(実行を中止します)。

SIGSEGVセグメンテーションエラー)と彼のいとこSIGBUSバスエラー)捕まえるかもしれませんが、自分がしていることを実際に知らない限り悪い考えです。これをキャプチャするための一般的なアプリケーションは、スタックトレースやその他のデバッグ情報を印刷することです。より進化したアプリケーションは、ある種のプロセス内メモリ管理を実装するか、仮想マシンエンジンで誤ったコマンドを見つけることです。

最後に、信号ではないことについて言及します。端末から入力を読み取るプログラムの行の先頭でCtrl+を押すと、プログラムはD入力ファイルの終わりに達したことを知らせます。これは信号ではありません。入力/出力APIを介して送信されます。 Like Ctrl+CとFriendsを使用してボタンを設定できますstty

答え2

まず、2番目の質問に答えてください。アプリケーションではキャプチャできませんが、他のすべてのシグナルはキャプチャできますSIGSTOP。このプロパティはデバッグに役立ちます。たとえば、正しいライブラリサポートを使用すると、スタックトレースを受け取り、生成して表示できます。セグフォルトが発生した位置。SIGKILLSIGSEGVSIGSEGV

man 7 signalLinuxコマンドラインに入力すると、各信号の機能(Linuxの場合)の正式な説明が得られます。http://linux.die.net/man/7/signal同じ情報がありますが、テーブルを読むのは難しいです。

しかし、シグナルの経験がなければ、簡単な説明でシグナルが実際にどのように機能するかを理解することは困難です。これの説明は次のとおりです。

キーボードでトリガー

  • SIGINTを打ったときに発生しますCTRL+C
  • SIGQUITによってトリガーされ、CTRL+\コアをダンプします。
  • SIGTSTPをクリックするとプログラムが一時停止しますCTRL+Z。とは異なり、プログラムが中断される前に端末を安全な状態にリセットする機会をSIGSTOP提供するキャッチ可能です。vi

端末相互作用

  • SIGHUP(「hangup」)は、プログラムの実行中にxtermが閉じられたとき(または端末から切断されたとき)に発生します。
  • SIGTTINSIGTTOUプログラムがバックグラウンドで実行されている間に端末から読み書きしようとすると、プログラムを停止します。このようなことが起こるためには、SIGTTOUプログラムが/dev/ttyデフォルトのstdoutだけでなくに書かなければならないと思います。

CPU例外トリガー

これは、プログラムが何か間違った操作を試みていることを意味します。

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

プロセス相互作用

  • SIGPIPEパイプリーダーがパイプの端を閉じてからパイプに書き込もうとすると、これが発生します。望むよりman 7 pipe
  • SIGCHLDSIGSTOPこれは、作成した子プロセスが終了または中断されたときに発生します(または同様の方法で)。

セルフシグナリングに便利

  • SIGABRT通常、abort()この関数を呼び出すプログラムが原因で発生し、デフォルトではコアダンプが発生します。一種の「パニックボタン」と同じです。
  • SIGALRMこれは、カーネルが指定された時間(秒)後にプログラムに渡すようにするalarm()システムコールによって発生します。とをSIGALRM参照してください。man 2 alarmman 2 sleep
  • SIGUSR1そして、SIGUSR2プログラムが望む方法で使用してください。プロセス間シグナルを送信するのに便利です。

管理者が送信しました

これらの信号は通常コマンドプロンプトで送信されますkillfgbgSIGCONT

  • SIGKILL止められない信号ですSIGSTOP。 1つ目は常にプロセスを即座に終了し、2つ目はプロセスを中断します。
  • SIGCONT一時停止したプロセスを再開します。
  • SIGTERMはい、キャプチャ可能なバージョンですSIGKILL

答え3

これは、以下を含むすでに提供されている他の回答に追加または追加されます。

  1. キル信号一覧 [重複]_
  2. さまざまな信号が送信される原因は何ですか?

ほとんどの信号の詳細については、Wikipediaを参照してください。https://en.wikipedia.org/wiki/Signal_(IPC)

最も一般的な信号の1つは、SIGINTプロセスの実行中に+をINT押して送信されるプログラム割り込み信号です。CtrlC

~からウィキペディア記事以上:

SIGINT

「信号中断」
SIGINTこの信号は、ユーザーがプロセスを中断したいときにプロセスを制御するターミナルによってプロセスに送信されます。これは通常Ctrl+を押して開始されますが、一部のシステムではC「削除」文字またはキーを使用できます。 [12]"break"

実行中のプロセスに手動でシグナルを送信する方法

[実行中のプロセスに]さまざまな信号が送信される原因は何ですか?

信号を送信する他のプログラムやキー入力に加えてあなたはそうです!

走ったりkill -lkill --list実行中のプロセスに送信できるすべてのシグナルのリスト

実行と出力の例:

$ kill -l
 1) SIGHUP       2) SIGINT       3) SIGQUIT      4) SIGILL       5) SIGTRAP
 6) SIGABRT      7) SIGBUS       8) SIGFPE       9) SIGKILL     10) SIGUSR1
11) SIGSEGV     12) SIGUSR2     13) SIGPIPE     14) SIGALRM     15) SIGTERM
16) SIGSTKFLT   17) SIGCHLD     18) SIGCONT     19) SIGSTOP     20) SIGTSTP
21) SIGTTIN     22) SIGTTOU     23) SIGURG      24) SIGXCPU     25) SIGXFSZ
26) SIGVTALRM   27) SIGPROF     28) SIGWINCH    29) SIGIO       30) SIGPWR
31) SIGSYS      34) SIGRTMIN    35) SIGRTMIN+1  36) SIGRTMIN+2  37) SIGRTMIN+3
38) SIGRTMIN+4  39) SIGRTMIN+5  40) SIGRTMIN+6  41) SIGRTMIN+7  42) SIGRTMIN+8
43) SIGRTMIN+9  44) SIGRTMIN+10 45) SIGRTMIN+11 46) SIGRTMIN+12 47) SIGRTMIN+13
48) SIGRTMIN+14 49) SIGRTMIN+15 50) SIGRTMAX-14 51) SIGRTMAX-13 52) SIGRTMAX-12
53) SIGRTMAX-11 54) SIGRTMAX-10 55) SIGRTMAX-9  56) SIGRTMAX-8  57) SIGRTMAX-7
58) SIGRTMAX-6  59) SIGRTMAX-5  60) SIGRTMAX-4  61) SIGRTMAX-3  62) SIGRTMAX-2
63) SIGRTMAX-1  64) SIGRTMAX    

たとえば、「警告」信号(たとえばSIGALRMALRMまたは信号番号14)を送信するには、次のいずれかを実行できます。

kill -SIGALRM <pid>
kill -ALRM <pid>
kill -14 <pid>

killpidに警告信号を送信するコマンドの例123456

kill -SIGALRM 123456
kill -ALRM 123456
kill -14 123456

以下を読んでくださいman kill(ハイライトを追加):

説明する

基本信号 kill はですTERM。利用可能な信号を使用-lまたは-L一覧表示します。特に有用な信号にはHUP、、、、およびINTがあります。 KILLSTOPCONT0-9代替信号は、-SIGKILLまたは3つの方法で指定できます-KILL 負のPID値は、プロセスグループ全体を選択するために使用できます。psコマンド出力のPGID列を参照してください。 PID-1は特別です。終了プロセス自体とinitを除くすべてのプロセスを表します。

到着興味のあるプロセスID(pid)を見つけます。、以下を実行してください。

ps aux | grep "some program name string or regular expression to search for"

出力ラインで一番左の信号番号を探します。左から2番目の列はPID(プロセスID)番号です。

プログラムで信号をキャッチする方法

1. バッシュから

「トラップ」、またはカスタム信号をキャプチャし、それに応じてアクションを実行します。強く打つSIGALRMプログラムでは次のことができます(信号をキャプチャします)。

trap <any_comand_to_run_when_signal_is_received> SIGALRM

以下は、カスタムbashプログラムでCtrl+ C"割り込み"(SIGINTまたはINTセマフォ)信号をキャプチャするために使用される一般的なトラップです。2

# Trap the Ctrl + C SIGINT signal from this point onward in the bash program so
# that whenever the user presses Ctrl + C, this program prints `Ctrl + C` and
# then exits with exit code 2 (change that to any exit code you'd like to
# return when Ctrl + C is pressed!).
trap 'printf "%s\n" " Ctrl + C"; exit 2' SIGINT

望むより:サーバー障害:Bashループ - コマンドでControl-Cを押したときにループをどのように停止しますか?

2. CとC++で

Linuxでは、CまたはC ++で指定された信号をキャプチャしてそれを処理するには、sigaction()(好ましくは)またはsignal()(あまり良くありませんが、C標準の一部)を使用できます。詳細な使用例と一緒に、これに対する包括的な答えを参照してください。スタックオーバーフロー:sigactionとsignalの違いは何ですか?

Bashでのkillシグナルの送信(通過)とキャッチ(通過)の例trap

次のプログラムは、trapコマンド(信号の受信とその動作)とkillコマンド(プロセスに信号を送る)を検索します。

  1. このbashムカデゲームを見てください:
    1. Ubuntuに尋ねてください:コマンドラインスネークゲーム?
    2. 私のeRCAGuy_hello_worldリポジトリはここにあります:ムカデゲーム.sh

関連情報