コンテンツにスキップ

プログラミング/割り込み

出典: フリー教科書『ウィキブックス(Wikibooks)』

割り込みの基本概念

[編集]

割り込みは、コンピュータシステムにおける重要な制御メカニズムです。通常のプログラム実行の流れを一時的に中断し、特定のイベントや緊急の処理を即座に対応するための仕組みです。ハードウェアやソフトウェアからのシグナルに応じて、現在実行中のタスクを中断し、別の処理に切り替えることができます。

割り込みハンドラの基本

[編集]

割り込みハンドラは、特定の割り込みイベントに対応するための特別な関数です。以下のコード例は、タイマー割り込みを処理する基本的な方法を示しています:

#include <signal.h>
#include <stdio.h>
#include <unistd.h>

int flag = 0;

void timer_interrupt_handler(int signum) {
    // タイマー割り込み時に実行される処理
    printf("タイマー割り込みが発生しました!\n");
    flag = 1;
}

int main() {
    // SIGALRMシグナルのハンドラを設定
    signal(SIGALRM, timer_interrupt_handler);
    
    // 3秒後にアラーム(割り込み)を発生
    alarm(3);
    
    // メインプログラムの処理
    for (;;) {
        printf("メインプログラムの実行中...\n");
        sleep(1);
        if (flag != 0) {
            break;
        }
    }
    
    return 0;
}

割り込みの種類

[編集]

割り込みは主に以下のカテゴリに分類されます:

ハードウェア割り込み

[編集]

ハードウェア割り込みは、物理デバイス(キーボード、マウス、ディスクなど)からのシグナルによって発生します。例えば、キーボード入力や外部デバイスの状態変化が典型的な例です。

ソフトウェア割り込み

[編集]

ソフトウェア割り込みは、プログラム内部で明示的に生成される割り込みです。システムコールの呼び出しや例外処理がこれに該当します。

例外割り込み

[編集]

例外割り込みは、プログラム実行中に発生する異常な状況(ゼロ除算、メモリアクセス違反など)に対応するための割り込みです。

例外処理の具体例

[編集]

以下のコード例は、ゼロ除算例外を処理する方法を示しています:

#include <signal.h>
#include <stdio.h>
#include <setjmp.h>

jmp_buf exception_env;

void division_by_zero_handler(int signum) {
    printf("ゼロ除算エラーを検出しました!\n");
    longjmp(exception_env, 1);
}

int safe_division(int numerator, int denominator) {
    // ゼロ除算の前にハンドラを設定
    signal(SIGFPE, division_by_zero_handler);
    
    // setjmpで例外発生時のジャンプポイントを設定
    if (setjmp(exception_env) == 0) {
        return numerator / denominator;
    } else {
        // 例外発生時の処理
        return 0;
    }
}

int main() {
    int result = safe_division(10, 0);
    printf("除算結果: %d\n", result);
    
    return 0;
}

割り込み管理の重要な概念

[編集]

割り込み優先度

[編集]

異なる割り込みイベント間には優先度が存在します。高優先度の割り込みは、低優先度の割り込みよりも優先的に処理されます。

コンテキストスイッチ

[編集]

割り込み発生時、現在のプログラムの実行状態(レジスタ、プログラムカウンタなど)を保存し、割り込みハンドラの処理後に元の状態に復帰する仕組みをコンテキストスイッチと呼びます。

割り込みの無効化と再有効化

[編集]

システムの安定性を確保するため、重要な処理中には割り込みを一時的に無効化し、処理完了後に再度有効化することがあります。

割り込み無効化の例

[編集]
#include <signal.h>
#include <stdio.h>

void critical_section() {
    sigset_t mask;
    
    // 全ての割り込みをブロック
    sigfillset(&mask);
    sigprocmask(SIG_BLOCK, &mask, NULL);
    
    // 重要な処理
    printf("クリティカルセクション:割り込み無効\n");
    
    // 割り込みを再有効化
    sigprocmask(SIG_UNBLOCK, &mask, NULL);
}

int main() {
    critical_section();
    return 0;
}

まとめ

[編集]

割り込みは、現代のコンピュータシステムにおいて不可欠な機能です。効果的な割り込み管理は、リアルタイムシステム、組み込みシステム、オペレーティングシステムの設計において極めて重要な概念となります。