割り込み (コンピュータ)

**割り込み**（わりこみ、）とは、コンピュータがその周辺機器などから受け取る要求の一種である。現在の多くのCPUは、割り込みを処理するための機能を備えている。

## 目的
割り込みの主な目的は、「周辺機器からの情報を、他の作業をしながらも取り落とすことなく受け取ること」であり、以下のような具体的な効果がある。

; CPU資源の有効利用
: 周辺機器の速度はCPUの処理速度より格段に遅いため、周辺機器が処理を行っている間、CPUが他の処理を行ったほうが効率がよい。その場合、周辺機器の処理の終了をCPU側から定期的にチェックする（ポーリングと呼ぶ）のは、他の処理の効率を落とすため望ましくない。このため、周辺機器の側から割り込みによって処理の終了を通知する方法がとられる。しかしながら、近年のCPUの高速化に伴い、GHz クラスのCPUを利用した場合は、1msec単位程度の周期的なポーリングを行う方式も研究されている。。
; 応答性の向上
: キーボード、マウスなどのユーザインターフェースは、入力の遅延や入力漏れが致命的な欠陥になる。この場合は割り込みを使ってユーザからの入力を確実に処理する必要がある。コンピュータがフリーズした場合でも、マウスカーソルの移動だけが反応することがあるが、これは割り込み処理だけが機能していることになる。
; 例外処理の効率化
: 周辺機器に障害が生じた場合、割り込みを用いることでプログラム側に障害を速やかに伝えることが可能になる。またプログラム上でも例外処理を本来の処理と分離して記述することを容易にする。
; 正確なタイミングの取得
: 画像表示、音楽の演奏や時計など、正確なタイミングで処理を行う必要がある機器を制御する場合、その機器が搭載している正確なタイマーによりタイマー割り込みを行い、CPU側に処理のタイミングを指示する。
; 透過的な実装
: 割り込み処理は割り込まれる側の処理から明示的に呼び出す必要がないため、一般には割り込まれる側の処理から個々の割り込み処理を意識する必要がなく、透過的な実装が可能となる。ただし、両者が同じリソースを使用する箇所では何らかの排他制御が必要となる。

## CPUの割り込み
### 割り込みの分類
CPUの割り込みは、大きく分けて**ハードウェア割り込み**（外部割り込み）と**ソフトウェア割り込み**（内部割り込み）に分類できる。一言で「割り込み」と言った場合、前者を指すことが多いため、後者のことをSWI (SoftWare Interrupt) と呼び区別する場合がある。

割り込みには以下のような種類が存在する。

* ハードウェア割り込み - 割り込み要求端子の変化によりCPU外部から発生する。
** ノンマスカブル割り込み(NMI) - マスク不可能な割り込み。
** マスカブル割り込み(狭義の) - マスク可能な割り込み。
* ソフトウェア割り込み(SWI) - CPU内部の要因で発生する。
** 狭義のソフトウェア割り込み(狭義のSWI) - CPUの割り込み命令によって発生する
** 例外、トラップ - 命令実行の前提条件を満足していない場合や、デバッグなど明示的な設定に基づいて発生する。

#### ハードウェア割り込み
ハードウェア割り込みはCPUの外部から要求されるものであり、CPUの割り込み要求端子をアサート（アクティブ化）された場合に発生する。

例えば、キーボードが押下されるなど周辺機からのデータ入力が発生した際に、**割り込み要求端子**(**IRQ端子**)の電圧をHIからLOWにしてアサートすることで、実行中のCPU命令実行が中断され、入力処理ルーチンの実行処理が*割り込まれる。*

CPUの割り込み要求端子には、割り込み処理を禁止できない**マスク不可能な割り込み** () と、割り込み処理の許可/禁止を制御できる**マスク可能な割り込み**（狭義のIRQ）の2種類の端子を備えている場合が多い。割り込みのマスクの設定は主にフラグレジスタに格納されており、割り込みの許可/禁止 () を操作するCPUの命令が用意されている。また、これらの端子が同時にアサートされた場合、優先順位がありNMIが優先される。一般に、周辺機からの入力にはOSで制御される必要があるため、IRQ端子に接続して使用されることが多い。一方、デバッグやハードウェアエラーなどの特殊な用途にはNMIが使用されることが多い。ところが、SPARCでは、割り込みの中で最も優先度が高いNMIであっても、その名称からの予想に反し、割り込みマスクを使用することで割り込み発生を禁止することができる。

**IRQ端子**のアサート方法は、信号の変化点を検出するエッジトリガと、信号のレベルで検出するレベルトリガがある。エッジトリガでは、立上がり又は立下りといった片方向の変化だけを検出する「片エッジ検出」と、両方ともを検出する「両エッジ検出」がある。PCIバスではレベルトリガ方式の割り込み信号線が取り入れられている。

CPU が割り込みを認識するためには、割り込みをサンプリングするタイミングで、割り込み信号がアサートされている必要がある。割り込みソースが多い場合、アサートされている信号のサンプリングを完了するまでのサイクル数が増加することになるため、割り込み許可状態とするサイクル数がどの位必要になるか、事前に(割り込み許可状態とサンプリング開始のタイミングやサンプリング完了に要するサイクル数など)割り込み回路設計情報を確認しておく必要がある。

CPU が割り込みを認識し、割り込み終了後に実行再開すべき PC やフラグレジスタを退避した後、割り込み処理ルーティンにてソフトウェアが割り込みを許可しない限りそれ以上の割り込みがネストしないように CPU が割り込みを自動的に禁止するタイプの CPU と、割り込みが認識されたレベルよりも優先度が高い割り込みに限りネストしても受け付けるタイプの CPU がある。後者の例としてPDP-11がある。初期のUNIXがPDP-11向けに開発されたことから、割り込みレベルを設定する命令がカーネル内で広く使用されており、他のアーキテクチャでもエミュレーションにより同機能を実装している。

#### ソフトウェア割り込み
ソフトウェア割り込みは、CPU内部においてCPU命令によって要求されるものや、命令実行に関わるモジュール（例えば、キャッシュ）の状態変化やエラーによって要求されるものがある。前者は、ソフトウェア割り込み命令によって発生するものであり、狭義のSWIとも言われる場合がある。また後者は、**[[例外処理|例外]]** (Exception) や**[[トラップ (コンピュータ) |トラップ]]** (Trap) と呼ばれ区別されることがある。

CPU命令(INT、TRAP、RST など)によって発生するソフトウェア割り込みは、実行可能な処理範囲がCPUモードによって制限されるようなCPUにおいて、システムコールを実現するために用いられる。例えば、通常のアプリケーションが動作するユーザモードでは実行できない命令であっても、SWIの後では特権モードに移行するため実行可能になる。

**例外**は、ゼロ除算、算術オーバーフロー、ページフォルトなどによって生じる例外処理の要求である。特に、ページフォルトはOSがメモリ空間を管理するのに重要な役割を果たす。

CPUがソフトウェア割り込みのための命令を直接サポートしていない場合、空いているハードウェア割り込み要求端子をアサートする手段を別途用意することによりソフトウェア割り込みをエミュレートすることがある。アーキテクチャによっては、この方法を正式なソフトウェア割り込みの実装としている。

別の定義として、ハードウェア割り込みから駆動する、そのハードウェア割り込みよりも優先度を下げた割り込みをしばしばソフトウェア割り込みと呼ぶ。この定義は、主にプロトコルスタックにて用いられる。プロトコルスタックは割り込み処理が多数のプロトコル階層にまたがるため処理に長時間を要することが多い。このため、全階層の割り込みをハードウェア割り込みで処理するとその間に別のパケットを受信してしまい、そのための割り込みが処理できずにパケットを破棄しなければならなくなる恐れがある。これを防ぐため、ハードウェア割り込みではネットワークカードからのパケット受信およびキューイングのみを処理し、その後の各階層での割り込み処理は別途ソフトウェア割り込みを起動して対応する実装がある。

例としてBSDによるプロトコルスタック実装では`splimp()`をネットワークカードからのハードウェア割り込み禁止、それより優先度が低い`splnet()`をプロトコルスタックでの割り込み禁止に使用している。プロトコルスタックではパケット送受信処理の多くを`splnet()`の下で実行することにより、プロトコルスタックでのパケット処理中に受信パケットの取りこぼしを防ぎながらプロトコルスタック同士の処理の衝突を防止している。`splimp()`は`splnet()`を含むため、ネットワークカードにてパケット受信処理を実行している間はプロトコルスタックでのパケット処理も禁止される。

### 割り込みコントローラ
CPUの割り込み要求端子は1本もしくは複数用意され、CPUの種類や実装によって異なる。

複数の周辺機からの割り込み要求が発生可能な場合、1つの割り込みハンドラ（後述）で処理を行うと、どの周辺機がどのような割り込み要求を発生させたのか判別する処理を、プログラム側で行う必要がある。これに対しPC/AT互換機などでは、ハードウェアとして複数のIRQ端子を用意して、割り込み要因毎に異なるハンドラに処理を移すことができるようにした構成をとれるようにしたものがある。この機能を持った回路のことを**割り込みコントローラ** (Interrupt Controller) と呼び、CPUのIRQ端子を外部で拡張して制御するものである。マイクロコントローラでは同一チップ内にCPUと複数の周辺機が内蔵され、割り込みコントローラも内蔵されるものが多い。

次に代表的な割り込みコントローラの例について述べる。

;Intel 8259 (Programmable Interrupt Controller, PIC)
:Intel 8086ファミリの割り込みコントローラ。IRQ 0-7の8本の割り込み端子を持ち、CPUに割り込み番号を伝える。各割り込み毎にマスクと優先順位を設定できる。PC/AT互換機ではこの機能を2つ搭載している。
;Z80ファミリ
: 集中的に管理する割り込みコントローラは存在せず、各周辺機（Z80 SIO, Z80 PIO, Z80 CTCなど）が、CPUに割り込みベクトル（後述）を出力する機能を持っていた。割り込み信号線のデイジーチェインの構成で優先順位をつける。
;ARMプロセッサ
: IRQと、より優先度の高い「高速割り込み」(FIQ) がある。FIQではIRQに比べ、一部のレジスタをスタックに入れず専用レジスタに退避するため、動作が速い。

## 割込処理
CPUに割り込みが生じると、現在実行している処理（命令）を停止して別の処理を実行する。割り込み後に実行される処理は、**[[割り込みハンドラ]]**もしくは**割り込みサービスルーチン** (Interrupt Service Routine, ISR) と呼ばれる。また、割込処理が終了しても、元の処理（割り込みが生じた時点に実行していた処理）に戻ってこられるように、元の処理の場所（アドレス）に関する情報（および元の処理の作業状態、**コンテキスト**と呼ばれる）を（多くの場合スタックに）保存しておく。

割込処理を実行するために、どこの場所（アドレス）に飛べば良いかを示す情報は、**割り込みベクタ**と呼ばれるテーブルに書かれている。割り込みベクタには、CPUの仕様により飛び先の命令のアドレスを書くこともあれば、命令そのものを書くこともある。後者の場合、割り込みハンドラの実装が割り込みベクタに納まるのであれば、別途割り込みハンドラ用のサブルーチンを実装しなくともよい。

## 割込処理のオーバーヘッド
割り込み処理ではイベントドリブンな処理を行うことができるため、割り込み処理に割り当てられたタスクについては効率的な処理が行える。しかしその一方、割り込み発生時には、CPUのレジスタの退避/復帰やプロセッサの特権レベル移行の処理など、少なからず処理にオーバーヘッドが生ずることとなる。このため、割り込みの発生頻度が高いシステムの場合、その処理によってシステム資源が占有されてしまい、本来の処理の応答性や処理速度に影響を与える場合がある。

状況によっては割り込みを使わず、ポーリングでフラグを定期的に確認するなどして、本来の処理との折り合いをつける方が、全体的なパフォーマンスが向上する場合がある。なお、一部のデバイスドライバでは、通常は割り込み動作を行い高負荷時にはポーリングで動作する仕組みを持ったものもある。

また、RISCプロセッサでは、割り込みが発生すると実行中のパイプラインが乱れ処理性能が低下するため、旧来の8ビットCISCプロセッサなどに比べると、割り込みによる相対的なパフォーマンス低下の影響が大きくなる。また投機的実行のペナルティなど複雑化したプロセッサ機能も、割り込みの際のオーバーヘッドを増大させる要因となる。

## 「割込み」という日本語
コンピュータのこの意味での「割込み」という語は、インタラプト（Interrupt）の訳ではなく、独立に作ったものである。和田英一によれば、1959年（昭和34年）の夏、パラメトロン計算機において、出力装置が直前の処理を終えたことを計算機に知らせる方法を議論していてアイディアを得た、という。

## 出典・脚注

## 関連項目

* CPU
* リアルタイム
* トラップ
* 排他制御