プロセス管理 2 シグナル プロセス間通信

シグナル

 Linuxにはプロセスにシグナルというイベントを送信して、プロセスを制御する機能がある。シグナルには、シグナル番号及びにシグナル名が割り当てられており、代表的なものに以下のシグナルがある。

 代表的なシグナル

シグナル番号 シグナル名 意味
1 HUP ハングアップ ( Hang Up )
2 INT 割り込み ( Interrupt )
3 QUIT 強制停止 ( Quit ) コアダンプ生成
9 KILL 強制終了 ( Kill )
15 TERM 終了 ( Terminate ) kill コマンドのデフォルトシグナル

   ユーザがプロセスにシグナルを送信する方法は3つ

  • シェルに割り当てられたキーの入力 ( ^C, ^Z, ^¥ など )

  • kill コマンド ( kill -HUP PID, kill -SIGINT PID, kill -9 PID など )

  • プログラムで kill() 関数で呼ぶ

 例えば、実行中のコマンドを停止するために^Cを押すと、シェルは^Cを解釈して、実行中のプロセスに SIGINT ( Interrupt Signal: シグナル番号2 ) を送信し、受け取ったプロセスは終了する。プログラムによっては、SIGINT を無視するなど、受け取ったシグナルによって挙動を制御するように作られたものもある。

実行例 無限ループするシェルスクリプトを作成する

$ vi loop

#!/bin/bash
until a == 1
do
  sleep 3600
done

:w
^Z

$ chmod 755 loop 
( シェルスクリプトに実行権限を与える )

$ ./loop
( 処理を無限に繰り返すため、フォアグランドで実行すると、シェルプロンプトが戻ってこない )

^C
( CTRL + C で INT ( Interupt Singnal ) が送信され、loop を終了する )

 上で作成したシェルスクリプト "loop" にtrap処理を挿入する

$ vi loop

#!/bin/bash
trap 'echo "CTRL+C is pressed."' 2
( trap にて SIGINT (2) を受信した時に中断せずに別の処理を実行する )

until a == 1
do
  sleep 3600
done

:w
Z

$ ./loop
^CCTRL+C is pressed.
( CTRL + C を押してもプロンプトが戻ってこない )

^Z
( CTRL + Z でサスペンドして kill コマンドでデフォルトの TERM シグナル ( Ternminate Signal:シグナル番号15 ) を送信する )

$ fg 
[1]  - continued  ./loop

$ kill %%
[1]  + terminated  ./loop

$ fg
fg: no current job
プロセスの終了
$ sleep 3600 &
[1] 28992

$ sleep 3601 &
[2] 28993

$ ps l
  UID   PID  PPID CPU PRI NI      VSZ    RSS WCHAN  STAT   TT       TIME COMMAND
  501 28992 24449   0  31  5  4268176    548 -      SN   s006    0:00.00 sleep 3600
  501 28993 24449   0  31  5  4269200    560 -      SN   s006    0:00.00 sleep 3601

$ kill -9 28992 28993 または $ kill -STGKILL 28992 28993
[2]  + killed     sleep 3601                                                                                                                                                                         
[1]  + killed     sleep 3600

top コマンドと pstree コマンド

 ps コマンドの他にプロセスの状態を表示するコマンドとして、 top コマンドがある。 top コマンドは実行中のプロセスの状態をダイナミックに表示する。 CPU やメモリの使用などでソートしたり、top から指定したプロセスにシグナルを送信することもできる。

 また、プロセスの親子関係をツリー表示できる pstree というコマンドがある。

プロセス間通信

 Linux 上である処理を完了するのに、一つのプロセスで完結する場合もあるが、複数のプロセスがコミュニケーションを取りながら同期したり、動作を変更して達成することが多々ある、これをプロセス間通信と呼ぶ。

 先ほど学習したパイプやシグナルも Linux の代表的なプロセス間通信の手法である。その他に下記の手法がある。

  • System V IPC ( Inter Process Communication )

  • ソケット それぞれ以下の特徴がある

  • パイプ 1つのプロセスの標準入出力を繋ぎ替える。パイプ ( | ) の左側にコマンド ( プロセス ) の標準出力を、右側のコマンド ( プロセス ) の標準入力を繋ぐことで通信を実現する。

  • シグナル 特定のシグナルの受診を持って特定の処理を開始するなど、同期を実現する。

  • 共有メモリ ( shared memory ) 特定のメモリ領域を複数のプロセスで共有することでメッセージの受け渡し等が行える。

  • セマフォ  ( semaphore ) 資源のロックを行い、複数のプロセス間で同時に書き起こしたりしないよう排他的処理を実現する。

  • メッセージキュー ( message queue ) キューにメッセージを格納しておき、複数のプロセス間での非同期の通信を実現する。

  • ソケット ネットワーク経由のホスト間のプロセスでの通信を実現する。