TL

割り込み処理の二段構え(上半分/下半分)

割り込みハンドラを軽くするだけで応答性とスループットが両立できる仕組みがわかります。上半分で最小限だけ受け、重い処理を下半分へ逃がす設計を原理から押さえられます。

応用割り込みsoftirqNAPIIRQ affinityLinuxカーネル最終更新: 2026-06-21
TL;DR要点だけ先に
  • 1.上半分(hardirq)は割り込み無効で走る最小区間。デバイス確認とACK、下半分の起動予約だけを行い即座に抜ける。
  • 2.下半分はsoftirq/tasklet/ワークキューに分かれる。softirqは並行・非眠り、taskletは同型の直列化、ワークキューだけがプロセス文脈で眠れる。
  • 3.IRQ affinityで割り込みをコアに固定し、NAPIは割り込みを止めてポーリングに切り替えることで高負荷時の割り込み嵐を消す。

なぜ二段に分けるのか

ハードウェア割り込みハンドラ(上半分、Linux では hardirq 文脈)は、原則として割り込みを無効化した状態で走ります。少なくともそのコアの同じ IRQ 線、設計によっては全 IRQ が抑止されます。この区間が長引くと、後続の割り込みが取りこぼされたり遅延し、タイマやネットワークの応答が崩れます。さらに hardirq 文脈ではスケジューラを呼べないため、眠る処理(メモリ確保で待つ、ロック待ちで眠る、ユーザー空間とのコピー)は一切できません。

そこで「最小限だけ即座にこなし、重い仕事は後回し」にします。前者が上半分、後者が下半分(bottom half)です。この発想は /os/interrupt-io/ で触れた「ISR は短く」の具体的な実装でもあります。

上半分が実際にやること

上半分は次の最小限に徹します。

1. 自分のデバイスが割り込んだか確認(共有IRQの切り分け)
2. デバイスに割り込みをACK(要因レジスタのクリア等)
3. 受信データの所在をメモ、または下半分の起動を予約
4. すぐ return(数マイクロ秒以内が理想)

ポイントは「処理しない、予約だけする」ことです。たとえば NIC なら、上半分はパケット本体を触らず「下半分よ、後でリングバッファを取りに来い」とだけ伝えて抜けます。

上半分で眠ると即カーネルパニック

hardirq 文脈で mutexmsleepkmalloc(GFP_KERNEL) のような眠りうる API を呼ぶと、スケジュール不能な文脈でスケジューラを呼ぶことになり破綻します。ここで使えるのは spinlock のみで、しかも下半分や他コアと共有するなら割り込み版(spin_lock_irqsave)が要ります。詳細は /os/kernel-locking-primitives/ を参照。

下半分の三つの実装

Linux の下半分は、性質の違う三つの仕組みに分かれます。どれを選ぶかは「眠れる必要があるか」「並行して走ってよいか」で決まります。

観点softirqtaskletワークキュー
実行文脈ソフト割り込み文脈(非眠り)softirq上で動く(非眠り)カーネルスレッド(眠れる)
眠れるか不可不可可(mutex・GFP_KERNEL可)
並行性同種が複数コアで同時実行同一taskletは全体で1つだけ直列ワーカ次第で並行も直列も可
数の制限種類は静的・少数(固定枠)動的にいくつでも生成可動的に生成可
典型用途ネットワーク・タイマなど高頻度ドライバの軽い遅延処理重い・眠る後処理
  • softirq:最も低レベルで高速。種類は NET_RX NET_TX TIMER などコンパイル時に固定された少数枠だけで、ドライバが勝手に増やせません。同じ softirq が複数コアで同時に走りうるため、内部のデータは自前でロックや per-CPU 化して守る必要があります。
  • tasklet:softirq の上に作られた使いやすい層。同一の tasklet はシステム全体で同時に一つしか走らないことが保証されるので、ロックを省ける場面が多い。ただし直列化ゆえスケールはしません。
  • ワークキュー:唯一**プロセス文脈(カーネルスレッド)**で走るため、眠ってよい。メモリ確保で待つ、ユーザー空間へコピーする、ミューテックスを取る、といった重い後処理はここに置きます。
softirq の暴走は ksoftirqd が引き取る

softirq は上半分の出口や local_bh_enable の直後に処理されますが、負荷が高く処理しきれない(おおむね一巡で捌けない)と、専用カーネルスレッド ksoftirqd がプロセス文脈で残りを引き取ります。これにより softirq が CPU を独占し続けて他タスクを餓死させる事態を防ぎます。

どこで処理するかは性能を左右する

下半分は便利ですが、割り込みが入ったコアでそのまま下半分も走るのが基本です。したがって特定の IRQ が一つのコアに集中すると、そのコアだけが過負荷になり、キャッシュ局所性も崩れます。これを制御するのが次の二つです。

IRQ affinity(割り込み親和性)

各 IRQ をどのコアに配送するかは /proc/irq/<N>/smp_affinity で固定できます。

# IRQ 24 をコア2,3だけに配送する(ビットマスク 0b1100 = 0xc)
echo c > /proc/irq/24/smp_affinity

狙いは二つ。第一に割り込み負荷の分散、第二に局所性の確保です。たとえば NIC の各受信キューを担当コアに固定すれば、そのコアのキャッシュにフロー状態が居座り、コア間でキャッシュ行を奪い合うコヒーレンシのコストを減らせます。irqbalance デーモンは自動でこれを調整しますが、低レイテンシ用途では手動固定が定石です。

affinity は下半分の場所も動かす

softirq や tasklet は割り込みを受けたコアで走るため、affinity を変えると上半分だけでなく下半分の実行コアも一緒に動きます。逆に言えば、affinity を無秩序にするとフローが毎回別コアに飛び、キャッシュミスとロック競合を量産します。

NAPI:割り込みを止めてポーリングへ

10Gbps 級の NIC では、パケット 1 個ごとに割り込みを上げると**割り込み嵐(interrupt storm)**になり、上半分の出入りだけで CPU が溶けます。これを解く緩和(interrupt mitigation)の仕組みが NAPI です。

1. パケット到着で受信割り込みが上がる
2. 上半分はその IRQ を「無効化」し、NAPI poll をスケジュール
3. 以後は割り込みでなく softirq(NET_RX) が、リングを「ポーリング」で一括回収
4. 1回の poll で budget(既定 64 個など)まで取る
5. もう来ない(空になった)ら割り込みを再び有効化して 1 に戻る

要点は「忙しい間は割り込みを切ってまとめて取り、暇になったら割り込みに戻す」という適応的な切り替えです。高負荷時はポーリングのスループット効率を、低負荷時は割り込みの低レイテンシを得る、いいとこ取りの設計と言えます。budget は他の softirq を餓死させない上限としても働きます。

試験・面接での頻出ポイント

「上半分でできないこと」を問われたら、眠ること(スケジュール)と時間のかかる処理、と即答できるように。tasklet と softirq の差は「同一 tasklet は全体で直列、同一 softirq は複数コアで並行」が決め手。ワークキューだけがプロセス文脈で眠れる、も頻出です。

関連する設計判断

二段構えは、応答性とスループットを両立させるためのレイテンシ設計そのものです。上半分を短く保つことは、より高優先度タスクの横取りを早く許すことにつながり、/os/kernel-preemption/ のレイテンシ最小化と同じ方向を向いています。また NAPI の「適応的にポーリングへ切り替える」発想は、高並行サーバーが多数の接続をまとめてさばく /os/epoll-io-uring/ のイベント駆動と本質的に同じ「まとめて処理する」最適化です。

まとめ

  • 上半分(hardirq):割り込み無効・非眠りの最小区間。ACK と下半分の予約だけして即抜ける。
  • 下半分:softirq(並行・高速・固定枠)、tasklet(同型は直列)、ワークキュー(プロセス文脈で眠れる)の三択。
  • IRQ affinity:割り込みをコアに固定し、負荷分散とキャッシュ局所性を両立。下半分の実行コアも一緒に動く。
  • NAPI:高負荷時は割り込みを止めてポーリングで一括回収し、暇になったら割り込みに戻す割り込み緩和。

OS Article

割り込み処理の二段構え(上半分/下半分)を実務で読む

TL;DRは入口です。実際に選ぶ・使う段階では、何を解決するか、何と比較するか、導入後にどこで詰まるかまで見る必要があります。

解決すること

割り込み

比較で見る軸

難易度: advanced / カテゴリ: OS / タグ数: 6

導入後に効く点

下半分はsoftirq/tasklet/ワークキューに分かれる。softirqは並行・非眠り、taskletは同型の直列化、ワークキューだけがプロセス文脈で眠れる。

先に潰すリスク

用語だけ覚えても、設計・実装・運用でどこに効くかを確認しないと判断を誤る。

数字・仕様の読み方
難易度
advanced
カテゴリ
OS
タグ数
6

判断チェックリスト

  • 自社の用途が「割り込み / softirq」に近いか確認する。
  • 強みである「上半分(hardirq)は割り込み無効で走る最小区間。デバイス確認とACK、下半分の起動予約だけを行い即座に抜ける。」が本当に評価軸になるか確認する。
  • 注意点の「用語だけ覚えても、設計・実装・運用でどこに効くかを確認しないと判断を誤る。」を運用で吸収できるか確認する。
  • 公開値や仕様値は、対象プラン・対象機種・対象リージョンまで確認する。
  • 既存システム、ID、ネットワーク、監視、バックアップとの接続方法を先に洗い出す。
  • 小さく試してから、本番移行、権限設計、障害時手順、コスト監視を決める。

次に確認する観点

割り込みsoftirqNAPIIRQ affinityLinux割り込みsoftirqNAPI
参考: 公式情報