試験運用中なLinux備忘録・旧記事

はてなダイアリーで公開していた2007年5月-2015年3月の記事を保存しています。

UNIXシグナルによるプロセス制御について

  1. シグナルについて
  2. 操作例
    1. プロセスの終了/強制終了
    2. プロセスの一時停止(サスペンド)
    3. 一時停止しているプロセスの再開
  3. 関連:プログラム中におけるシグナルの処理とその対象外シグナル

シグナルについて

(UNIX系OSの用語としての)「シグナル」という通知をプロセスに送信することにより、対象プロセスの動作状態を変更することができる。*1
シグナルには色々な種類があり、一覧は「signal」のmanページなどを参照。
シグナルは

  • プログラムが(メモリの不正な参照などで)異常終了した、いわゆる「落ちる」動作をしたときにSIGSEGVシグナルが発生
  • フォアグラウンドプロセスにCtrl+Cを実行するとSIGINTシグナル*2が発生して終了する
  • フォアグラウンドプロセスにCtrl+Zを実行するとSIGTSTPシグナル*3が発生して一時停止(サスペンド)状態になる
  • パイプで接続された複数のプロセス間において、書き込み先のプロセスが先に終了したなどで既に閉じてしまったパイプへ書き込みを行おうとしたときにSIGPIPEシグナルが書き込み元プロセスに通知され、終了する*4
  • 子プロセスを生成したとき、そのプロセスが終了するとSIGCHLDシグナルが親プロセスに通知される

などのパターンで自動的に発生する場合があるが、手動で送信することもでき、

  • kill(対象のプロセスID(複数可)のみに通知)
  • killall(該当するプロセス名(複数可)のプロセス全てに通知)
  • pkill(該当するパターンにマッチする名前のプロセス全てに通知)

といったコマンドを用いる。
いずれもシグナル名の「SIG」の後ろの部分を「-」につなげたオプション指定(「SIGSTOP」なら「-STOP」)を行う。「-9」(-KILLと等価)のように直接数値による指定を行うこともできる。

操作例

プロセスの終了/強制終了
プロセスを終了させるにはkill系コマンドにおける既定のシグナルであるSIGTERMを用い、シグナルの種類を示すオプションは付けない(あるいは-TERM指定)。

(プロセスIDによる指定)
$ kill [プロセスID...]
(プロセス名による指定)
$ killall [プロセス名...]
もしくは
$ pkill [プロセス名のパターン]

これを実行しても何らかの理由によりプロセスが終了しない場合、SIGKILLシグナルを送ることで強制的にプロセスを終了させることができる場合が多い。*5

(プロセスIDによる指定)
$ kill -KILL [プロセスID...]
(プロセス名による指定)
$ killall -KILL [プロセス名...]
もしくは
$ pkill -KILL [プロセス名のパターン]

プロセスの一時停止(サスペンド)
プロセスを一時停止するシグナルは色々あるが、SIGSTOPを用いるのがよい。

(プロセスIDによる指定)
$ kill -STOP [プロセスID...]
(プロセス名による指定)
$ killall -STOP [プロセス名...]
もしくは
$ pkill -STOP [プロセス名のパターン]

のようにする。

一時停止しているプロセスの再開
サスペンドされたプロセスの再開にはSIGCONTというシグナルを用いる。

(プロセスIDによる指定)
$ kill -CONT [プロセスID...]
(プロセス名による指定)
$ killall -CONT [プロセス名...]
もしくは
$ pkill -CONT [プロセス名のパターン]

topのような端末上のコマンドやnanoなどの端末アプリケーションではうまく再開されないこともある。

関連:プログラム中におけるシグナルの処理とその対象外シグナル

シグナルはプログラムの中で「特定のシグナルが発生した場合に行う処理」の定義とその関連付け*6を行うことで「捕捉」ができる仕組みになっているが、SIGKILLとSIGSTOPは特別にこの対象から外れる。
(2015/1/14)manページのリンク先を修正

関連URL:

*1:これはGLibというライブラリで用いられる用語の「シグナル」とは機能が異なるが、どちらも何らかのイベント(出来事)を通知するものである点は共通する

*2:割り込み[interrupt]より

*3:端末[terminal]からの停止[stop]通知

*4:例として、「seq 100000000」を実行すると非常に長い連番を生成するが、「seq 100000000 | head」を実行すると10行だけ表示した時点でパイプが切れ、seqコマンドはSIGPIPEにより終了する

*5:稀に(特殊な状況下において)これを送ってもプロセスが終了しないこともある

*6:C言語sigaction()という関数による