割り込みとは何か?ポーリングとの違いから理解する【組み込み入門】

目次

はじめに

初心者さん

割り込みって、“イベントが来たら勝手に処理される仕組み”ですよね?

エンジニアくん

それも間違いではないけど、“CPUが何をしているか”を理解しないと後で苦労するよ

初心者さん

たしかに…ポーリングとの違いも、実はちゃんと説明できないかもです

組み込み開発をしていると、必ず登場するのが「割り込み(Interrupt)」です。

しかし実際には、

  • なんとなく使っている
  • ポーリングとの違いが曖昧
  • サンプルコードをそのまま使っている

という人も少なくありません。

特に初心者のうちは、

「イベントが来たら勝手に処理される便利機能」

くらいの感覚で理解してしまいがちです。

ですが実際の割り込みは、

  • CPU停止
  • コンテキスト保存
  • スタック退避
  • 優先度制御

など、CPUの動作そのものに深く関係しています。

この記事では、
割り込みの基本を「ポーリングとの比較」から整理しながら、

  • なぜ組み込みで重要なのか
  • CPU内部で何が起きているのか
  • なぜ設計が難しくなるのか

を、組み込み初心者向けに分かりやすく解説します。

割り込み処理解説シリーズ

本記事は「割り込み処理解説」シリーズの1つです。

割り込み処理解説シリーズの全体像はこちら

割り込み記事シリーズ一覧です。
こちらのまとめ記事で全体像を整理しています。

  1. 割り込みとは何か?ポーリングとの違いから理解する【組み込み入門】(この記事)
  2. 割り込み処理でやってはいけないこと5選|組み込み設計の落とし穴
  3. 割り込みは「処理を書く場所」ではない|組み込み設計の本質
  4. 割り込み×状態遷移設計|イベント駆動型組み込みの基本パターン
  5. 割り込み優先度設計の考え方|リアルタイム性を壊さないために
  6. 割り込みとRTOSなし構成の違いとは?設計思想の本質を整理する

割り込みとは何か?

初心者さん

割り込みって、“別の処理が同時に動く”感じですか?

エンジニアくん

実際には“途中で処理を切り替えている”んだ。CPUが増えてるわけじゃないよ

割り込み(Interrupt)とは、

👉 CPUが実行中の処理を一時中断し、優先度の高い処理を先に実行する仕組み

です。

例えば組み込み機器では、

  • ボタンが押された
  • UARTでデータを受信した
  • タイマ時間になった
  • センサ値が更新された

など、さまざまな「イベント」が発生します。

こうしたイベントが発生すると、
CPUは現在の処理を一旦止めて、「割り込み処理(ISR: Interrupt Service Routine)」を実行します。

そして処理が終わると、
再び元の処理へ戻ります。


イメージするとこんな感じ

例えばCPUがメインループを実行中に、
UART受信が発生したとします。

C
while(1) {
    main_task();
}

通常は main_task() を実行していますが、
途中でUART受信イベントが発生すると、

割り込み処理の流れ

という流れになります。

ここで重要なのは、

👉 CPUは「同時に動いている」のではなく、一時的に処理を切り替えている

という点です。

ポーリングとは何か?

ポーリング(Polling)は、

👉 CPUが自分で状態を確認し続ける方式

です。

例えばボタン入力なら、以下のようになります。

C
while(1) {
    if (BUTTON == ON) {
        // ボタン処理
    }
}

CPUが延々と、

「ボタン押された?」
「まだ?」
「今は?」

を確認し続けるイメージです。


割り込みとポーリングの違い

一番の違いは「誰が気づくか」

ポーリング

CPUが自分から確認しに行く

割り込み

イベント側がCPUを呼び止める

この違いがあります。

違いのまとめ

まとめると、割り込みとポーリングの違いは以下となります。

項目割り込みポーリング
反応性高いループ周期に依存
CPU効率無駄が少ない常に監視するため負荷あり
実装難易度やや高い比較的簡単
設計の難しさ高い低め

ポーリングの問題点

初心者向けサンプルでは、
ポーリングは非常によく使われます。

実装が簡単だからです。

しかし実際の組み込み製品では、
ポーリングだけでは厳しいケースが多くあります。

例えば:

  • CPUが無駄に回り続ける
  • 消費電力が増える
  • 他処理が増えると監視漏れが起きる
  • 応答遅延が発生する

といった問題があります。


例えばこんな問題が起きる

C
while(1) {
    heavy_task();

    if (BUTTON == ON) {
        // ボタン処理
    }
}

もし heavy_task() に時間がかかると、

👉 ボタンを押しても反応が遅れる

可能性があります。

これが「ポーリングはループ周期に依存する」ということです。

なぜ組み込みでは割り込みが重要なのか?

組み込み機器は、

  • 限られたCPU性能
  • リアルタイム要求
  • 低消費電力設計
  • 小さいメモリ

という制約があります。

ポーリングでは、

  • 無駄にCPUを回し続ける
  • 低消費電力にできない
  • 応答遅延が出る

といった問題が発生します。

そのため、

「イベントが来たときだけ動く」

というイベント駆動型設計が非常に重要になります。

そこで使われるのが割り込みです。


割り込みの流れ(CPU内部)

割り込み発生時、CPU内部では大まかに以下が行われます。

割り込み処理の流れ

この、

  • 「状態退避」
  • 「復帰」

があるため、
割り込みは実はかなり複雑です。


ISR(割り込み処理)では何をするのか?

初心者が最初にやりがちなのが、

👉 ISRの中に大量の処理を書く

ことです。

しかし実際には、
ISRはできるだけ短くするのが基本です。

例えば:

C
volatile int uart_rx_flag = 0;

void UART_IRQHandler(void) {
    uart_rx_flag = 1;
}

ISRでは「イベント発生だけ通知」して、
本処理はメインループ側で行う設計がよく使われます。

なぜISRに重い処理を書いてはいけないのかは、こちらの記事で詳しく解説しています。

割り込みと共有変数では volatile の理解も重要です。
volatileについてはこちらの記事で解説しています。


割り込みと状態遷移設計

実際の組み込み開発では、

「割り込みの中ですべて処理する」

のではなく、

👉 割り込みは“イベント通知”だけ行う

という設計がよく使われます。

例えば:

  • UART受信完了
  • ボタン押下
  • タイマ満了

などを「イベント」として扱い、
メインループ側の状態遷移で処理する形です。

割り込みと状態遷移

このような「イベント駆動型設計」は、
組み込みソフトで非常によく使われる基本パターンです。

逆にISRへ重い処理を書きすぎると、

  • リアルタイム性低下
  • 他割り込み遅延
  • デバッグ困難化

などの問題につながります。

状態遷移設計については、
こちらの記事で詳しく解説しています。

割り込みとスタック領域の関係

割り込み発生時、CPUは現在の状態を「スタック領域」に保存しています。

例えば:

  • プログラムカウンタ(PC)
  • レジスタ
  • ステータスレジスタ

などが退避されます。

つまり割り込みは、

👉 スタック領域を使って「処理の途中状態」を保存している

ということです。

この仕組みがあることで、
ISR実行後に元の処理へ安全に戻ることができます。

逆に言えば、

  • スタック不足
  • 異常なネスト
  • 再帰暴走

などが起きると、
割り込み処理にも大きな影響が出ます。

スタック領域については、
こちらの記事で詳しく解説しています。

割り込みは「main()の前」から準備されている

実は割り込み処理は、
main() が始まった後に突然使えるようになるわけではありません。

組み込みソフトでは、
main()実行前の「スタートアップコード」で、

  • スタック初期化
  • ベクタテーブル設定
  • CPU初期化

などが行われています。

つまり割り込みは、

👉 CPU起動直後の初期化処理とも深く関係している

ということです。

特にARMマイコンでは、
割り込みベクタテーブルや初期スタック設定が非常に重要になります。

スタートアップコードについては、
こちらの記事で詳しく解説しています。

割り込みが“魔法”ではない理由

割り込みは便利ですが、
決して「何でも即時実行できる魔法」ではありません。

実際には、

  • スタック消費
  • 割り込み優先度
  • ネスト
  • 排他制御
  • 共有変数
  • リアルタイム性

など、多くの設計課題があります。

ここを理解しないまま使うと、

  • たまにフリーズする
  • 再現しない不具合
  • タイミング依存バグ

など、非常に厄介な問題につながります。

割り込みが連続する状況では、割り込み優先度設計も重要です。
割り込み優先度設計はこちらの記事で解説しています。


まとめ

  • 割り込みは「CPUを一時停止して優先処理を行う仕組み」
  • ポーリングは「CPUが自分で確認し続ける方式」
  • 組み込みではイベント駆動設計が重要
  • 割り込みは便利だが、設計難易度は高い
  • ISRには原則として重い処理を書かない

次回予告

次回は、

「割り込み処理でやってはいけないこと」

について、実務目線で解説します。

  • なぜ printf が危険なのか
  • なぜ malloc が嫌われるのか
  • なぜ重い処理を書いてはいけないのか

など、現場で本当に問題になるポイントを整理していきます。

この記事が参考になった方へ

割り込み処理については、
こちらのまとめ記事で全体像を整理しています。

また当サイトでは、
割り込み理解に必要なC言語文法やメモリ構造についても実務目線で解説しています。

エンジニアとして技術を学ぶことは重要ですが、
キャリアや副業についても同時に考える必要があります。

副業の現実や市場価値、今後のキャリア戦略については、
こちらの記事でまとめています。

技術に関するご相談・開発・自動化ツール作成・記事執筆などのご依頼も承っています。

小さなご相談からでもお気軽にご連絡ください。

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!

この記事を書いた人

組み込みソフトエンジニアとして働きながら、
C言語・メモリ・ポインタなどの基礎から実務まで解説しています。

副業・キャリアについても実体験ベースで発信中です。

X・Qiita・noteでも発信しています。
X:更新情報・日常
Qiita:技術発信
note:キャリア・副業

▼まずはここから読むのがおすすめ
C言語文法シリーズ
メモリ領域解説シリーズ
割り込み処理解説シリーズ
ソフトウェア設計解説シリーズ
キャリアと副業ロードマップ

コメント

コメントする


目次