Linuxプロセスシグナルの発生メカニズム

シグナルの基本概念

シグナルはLinuxにおけるプロセス間通信の一種であり、非同期イベント通知を実現します。プロセスはシグナルを受信することで、特定の動作を実行したり状態を変更したりします。

シグナルの種類と特性

kill -lコマンドで確認できるシグナルは62種類あり、1〜31番が通常シグナル、32〜64番がリアルタイムシグナルです。通常シグナルは到着の有無のみを記録しますが、リアルタイムシグナルはキューイングが可能です。

# シグナル一覧表示
$ kill -l
 1) SIGHUP       2) SIGINT       3) SIGQUIT      4) SIGILL
 5) SIGTRAP      6) SIGABRT      7) SIGBUS       8) SIGFPE
...

シグナルの動作変更

シグナルハンドラはsignal()関数で登録可能ですが、SIGKILL(9)とSIGSTOP(19)は変更不可です。

#include <signal.h>
#include <iostream>

void custom_handler(int sig_num) {
    std::cout << "受信シグナル: " << sig_num << std::endl;
}

int main() {
    signal(SIGINT, custom_handler);
    while(1) pause();
    return 0;
}

シグナル発生の方式

キーボード入力

Ctrl+CはSIGINT(2)、Ctrl+\はSIGQUIT(3)を送信します。これらのシグナルは端末ドライバが検出し、フォアグラウンドプロセスに配送されます。

システムコール

kill(), raise(), abort()などの関数で明示的にシグナルを送信できます。

#include <sys/types.h>
#include <signal.h>

// プロセス終了デモ
int main() {
    pid_t current_pid = getpid();
    kill(current_pid, SIGTERM);
    return 0;
}

カスタムkillコマンド実装

#include <cstdlib>
#include <iostream>

int main(int argc, char* argv[]) {
    if(argc != 3) {
        std::cerr << "使用方法: " << argv[0] << " [シグナル番号] [PID]" << std::endl;
        return 1;
    }
    
    int sig_num = std::atoi(argv[1]);
    int target_pid = std::atoi(argv[2]);
    kill(target_pid, sig_num);
    
    return 0;
}

ハードウェア例外

ゼロ除算や不正メモリアクセスなどのハードウェア例外は、CPUのステータスレジスタを設定し、OSが対応するシグナル(SIGFPE, SIGSEGVなど)を送信します。

#include <iostream>

int main() {
    int val = 10;
    int result = val / 0;  // SIGFPE発生
    return 0;
}

コアダンプ機能

特定のシグナル受信時にはコアダンプファイルが生成されます。デバッグ時に有用です。

# コアダンプ有効化
$ ulimit -c unlimited

# デバッグ方法
$ gdb ./program core.pid
(gdb) bt

コアダンプ関連シグナル

  • SIGQUIT (3) - コアダンプ生成後終了
  • SIGABRT (6) - 異常終了
  • SIGFPE (8) - 算術例外
  • SIGSEGV (11) - メモリ違反

タグ: linux シグナル プロセス制御 システムコール コアダンプ

5月26日 03:55 投稿