概要
本記事では、Linux のプロセス間通信の一形態であるシグナルについて説明します。kill、pkill、killall コマンドでプロセスに対してシグナルを送信する方法について解説します。
シグナル
シグナルは、プロセス間通信 (Inter-Process Communication, IPC) の一形態で、特定のイベントが発生したことをプロセスに通知するために使用されます。シグナルは、プロセスに対して非同期に送信される短いメッセージであり、プロセスが特定のアクションを実行するためのトリガーとなります。
シグナルは整数値で識別され、各シグナルには特定の意味が割り当てられています。例えば、SIGINT
はキーボードの割り込み (Ctrl+C
) を示し、SIGTERM
はプロセスの終了要求を示します。シグナルの詳細なリストは kill -l
コマンドで確認できます。
シグナルの種類
シグナルの一覧
以下にシグナルの一覧をテーブル形式で示します:
シグナル名 | 番号 | 説明 | デフォルト動作 |
---|---|---|---|
SIGHUP | 1 | ハングアップ (端末の切断) | 終了と再読み込み |
SIGINT | 2 | 割り込み (Ctrl+C ) |
終了 |
SIGQUIT | 3 | 終了 (Ctrl+\ ) |
コアダンプと終了 |
SIGILL | 4 | 不正命令 | コアダンプと終了 |
SIGTRAP | 5 | トレース/ブレークポイントトラップ | コアダンプと終了 |
SIGABRT | 6 | プロセス中断 | コアダンプと終了 |
SIGBUS | 7 | バスエラー | コアダンプと終了 |
SIGFPE | 8 | 浮動小数点例外 | コアダンプと終了 |
SIGKILL | 9 | 強制終了 (キャッチ不可) | 終了 |
SIGUSR1 | 10 | ユーザー定義シグナル 1 | 終了 |
SIGSEGV | 11 | セグメンテーション違反 | コアダンプと終了 |
SIGUSR2 | 12 | ユーザー定義シグナル 2 | 終了 |
SIGPIPE | 13 | パイプ破損: 書き込み側のプロセスなし | 終了 |
SIGALRM | 14 | タイマーシグナル | 終了 |
SIGTERM | 15 | 終了要求 | 終了 |
SIGSTKFLT | 16 | スタックフォルト | 終了 |
SIGCHLD | 17 | 子プロセスの状態変化 | 無視 |
SIGCONT | 18 | 停止していたプロセスの継続 | 継続 |
SIGSTOP | 19 | プロセスの停止 (キャッチ不可) | 停止 |
SIGTSTP | 20 | 端末からの停止 (Ctrl+Z) | 停止 |
SIGTTIN | 21 | バックグラウンドプロセスの tty 入力 | 停止 |
SIGTTOU | 22 | バックグラウンドプロセスの tty 出力 | 停止 |
SIGURG | 23 | 緊急データの到着 (ソケット) | 無視 |
SIGXCPU | 24 | CPU 時間制限を超過 | 終了 |
SIGXFSZ | 25 | ファイルサイズ制限を超過 | 終了 |
SIGVTALRM | 26 | 仮想タイマーシグナル | 終了 |
SIGPROF | 27 | プロファイリングタイマーシグナル | 終了 |
SIGWINCH | 28 | ウィンドウサイズの変更 | 無視 |
SIGIO | 29 | I/O 可能 | 終了 |
SIGPOLL | 29 | ポーリングイベント (SIGIO と同じ) | 終了 |
SIGPWR | 30 | 電源障害 | 終了 |
SIGSYS | 31 | 不正なシステムコール | コアダンプと終了 |
SIGRTMIN ~ SIGRTMAX | 34~64 | リアルタイムシグナル | 終了 |
ユーザー定義シグナル
ユーザー定義シグナルは、ユーザーが自由に定義してプログラムやスクリプトが自由に使用できるシグナルです。
シグナル名 | 番号 | 説明 | デフォルト動作 |
---|---|---|---|
SIGUSR1 | 10 | ユーザー定義シグナル 1 | 終了 |
SIGUSR2 | 12 | ユーザー定義シグナル 2 | 終了 |
SIGRTMIN ~ SIGRTMAX | 34~64 | リアルタイムシグナル | 終了 |
シグナルの送信
シグナルは kill
コマンド、pkill
コマンド、killall
コマンドを使用して、プロセスに送信できます。
kill コマンド
kill -TERM <pid>
kill
コマンドの基本的な使用方法は以下の通りです。
シグナルの種類は、シグナル名または番号で指定します。
シグナルを指定しない場合、デフォルトで SIGTERM が使用されます。
# プロセスID 1234 に SIGTERM シグナルを送信
kill 1234
# プロセスID 1234 に SIGKILL シグナルを送信
kill -9 1234
# プロセスID 1234 に SIGUSR1 シグナルを送信
kill -USR1 1234
pkill コマンド
pkill
コマンドは、プロセス名やその他の属性でプロセスを検索し、条件に一致するプロセス全てにシグナルを送信するためのコマンドです。
シグナルを指定しない場合、デフォルトで SIGTERM が使用されます。
# "myprocess" という名前のプロセスに SIGTERM シグナルを送信
pkill myprocess
# "myprocess" という名前のプロセスに SIGKILL シグナルを送信
pkill -KILL myprocess
# ユーザー名が "user1" のプロセスに SIGUSR1 シグナルを送信
pkill -USR1 -u user1
killall コマンド
killall
コマンドは、指定された名前と一致するすべてのプロセスに対してシグナルを送信するためのコマンドです。
プロセス名は完全一致で判定され、シグナルを指定しない場合は SIGTERM が使用されます。
# "myprocess" という名前のすべてのプロセスに SIGTERM シグナルを送信
killall myprocess
# "myprocess" という名前のすべてのプロセスに SIGKILL シグナルを送信
killall -9 myprocess
# "myprocess" という名前のすべてのプロセスに SIGUSR2 シグナルを送信
killall -s SIGUSR2 myprocess
シグナルのハンドリング
プロセスはシグナルを受け取ったときに特定のアクションを実行するように設定できます。
signal()
関数を使用して、シグナルとそのシグナルを受け取ったときのコールバック関数を登録します。
シグナルを処理する
#include <stdio.h>
#include <signal.h>
#include <unistd.h>
void handle_signal(int signal) {
if (signal == SIGUSR1) {
printf("Received SIGUSR1\n");
}
}
int main() {
// SIGUSR1 シグナルを受信したときのハンドラを設定
signal(SIGUSR1, handle_signal);
// 無限ループでシグナルを待つ
while (1) {
printf("Waiting for SIGUSR1...\n");
sleep(1);
}
return 0;
}
このプログラムは、SIGUSR1
シグナルを受け取ると “Received SIGUSR1” と表示します。
シグナルを無視する
特定のシグナルを無視するように設定することもできます。これには SIG_IGN
定数を使用します。
#include <signal.h>
#include <unistd.h>
int main() {
// SIGHUP シグナルを無視
signal(SIGHUP, SIG_IGN);
// 無限ループでシグナルを待つ
while (1) {
sleep(1);
}
return 0;
}
シグナルを受け取らない場合
シグナルを受け取らない、つまりシグナルハンドラが設定されていない場合、各シグナルにはデフォルトの動作があり、そのデフォルト動作が実行されます。シグナルのデフォルト動作は、シグナルの種類によって異なります。
コメント