K3の住民

最近はレア社のゲームについては書いていませんが、一応レア社のゲームが一番好きな人です。『雪圀』で"圀"は"国"とほぼ同義ですが、国ではありませんって当たり前か(笑)。

ハードやソフトにおける割り込みについて色々。

皆さん、こんにちは。雪圀です。
今回は、ハード・ソフトにおける知っておくとかなり便利な「割り込み」について
書いていこうかなと思います。

割り込みとは何ぞ?

割り込みは今実行しているプログラムを中断し、割り込みが起こったときに使われる
処理(これを割り込みハンドラという)を実行することです。これを知っておくと
主にプログラム関連(特に組み込み系)では非常に役立ちますが、僕的に割と苦手な
人が多い印象です。
そんなわけで(実は僕もあまり「割り込み」については自信は無いので間違ってる
かもしれませんが)割り込みについて出来るだけ分かりやすく解説していこうと
思います。

「割り込み」について詳しく[1]: ポーリング

その対極の存在として「ポーリング」が存在します。「ポーリング」というのは、
ソフト側がどの処理が行われるかいちいち確認する方法です。どの処理かは分かって
いないので毎度毎度チェックが必要です。

どういうことか?例えばあなたが5人の囚人が脱走しないかチェックをし、もし脱走
しそうな囚人がいたら止めるという仕事に就いていたとしましょう。
そして、1人目から5人目まで順番にチェックするとします。

f:id:ryoryoau24:20180310205100p:plain

ここで、誰かが脱走しそうだということをあなたは知りました。それが1人目だと
囚人は1人目から順番に数えていくのですぐに止めることが出来ます。
しかし、5人目であった場合、1人目、2人目、・・・と数えていくので、止めるのが
遅くなってしまいます。そんなことしてる間に5人目の囚人は逃げてしまうでしょう。

つまり、何が言いたいのかと言うと、ポーリングはチェックする処理が多ければ多い
ほど実行に時間がかかる、というのが難点なのです。
その難点を解決する方法の一つとして、「割り込み」があるのです。

「割り込み」について詳しく[2]: 割り込み

「ポーリング」について理解したなら分かると思いますが(それでも分からないなら
僕の説明不足ですね・・・)「割り込み」のメリットは「応答性に非常に優れて
いる」こと。これにつきます。

何故か?それは、割り込み信号がCPUに入ることによって割り込みを発生させている
からです。

先ほどの例で考えてみましょう。
例えば、5人の囚人の中で、5人目は特に要注意人物であったとします。

f:id:ryoryoau24:20180310211558p:plain

5人目の囚人だけは脱走しそうになると、警報機が鳴ります。あなたはまた囚人が
脱走しないかチェックしていたとして、5人目の囚人が脱走しようとしました。
すると、警報機が鳴り、あなたはすぐさま5人目の囚人のところに行き、5人目の囚人
を止めることが出来ました。

f:id:ryoryoau24:20180310212605p:plain

この例で説明すると、警報機で鳴っている音がその信号ですね。
ところで、あなたは警報機が鳴ると5人目の囚人のところに行きますよね?何故5人目
の囚人のところに行けるのでしょうか?それは、あなたが5人目の囚人が要注意人物
であることを知っているからですね。

この割り込みの発生による処理を実行させるには、予め割り込みハンドラを登録
する、ということが必要でこの登録するリストを「割り込みベクタテーブル」と
呼びます。

つまり、あなたは「5人目の囚人が要注意人物であること」を「要注意人物リスト」
という名の割り込みベクタテーブルに書き込んでいるわけですね。

f:id:ryoryoau24:20180310214437p:plain

しかし、もし仮にこの割り込みハンドラが2つ割り込みベクタテーブルに登録されて
いて、2つ同時に割り込みが起こってしまったなら、どう処理するのでしょうか?
それについては後ほど説明していきます。

割り込みの種類

割り込みにはCPU以外での割り込みとCPU内部の割り込みが存在します。

外部割り込み
CPU外部の割り込み要求端子(割り込み信号が電気的にここに入ることにより
割り込みが発生する)が変化することで発生させる割り込みで、「ハードウェア
割り込み」とも呼ばれます。一般的な割り込みはこれを表すことが多いです。
この外部割り込みには割り込みが禁止出来ない「NMI(Non-Maskable Interrupt)」
と割り込みが禁止出来る「Maskable Interrupt」の2種類があります。

NMI(Non-Maskable Interrupt)
最初から書くべきだったとは思いますが「Interrupt」は「割り込み」を意味します
だから日本語では「ノンマスカブル割り込み」とも呼ばれます。
基本的に割り込みが出来るCPUには、許可する・禁止する機能があり、これにより
「割り込み要求端子((IRQ(Interrupt ReQuest)とも言う)」に余計なことを
させない、と言うことが出来ます(もし無ければ割り込みが常に起こってしまう等の
現象が起こることもある)。
しかし、このNMIだけは別で、割り込みを禁止することが出来ません。だから、
(使わないことは無いと思うが)使わない場合はハード側でそれなりの処置が必要
な場合もあります。
NMIはハードのエラーが起こったときにハードウェアリセットをさせる(ハード
ウェアリセットとNMIは別々である場合も一応ある)ときやデバッグをするとき等
特殊な用途で使われることが多く、それら以外の割り込みハンドラは基本的に
「Maskable Interrupt」で割り込みさせます。

Maskable Interrupt
日本語では「マスカブル割り込み」と呼ばれ、割り込みを禁止させることが
出来ます。許可する場合は、ハード側で何らかの処置が必要な場合があります。

因みに先ほど割り込みが2つ同時に起こってしまった場合、どのように処理される
のかということを問うたと思います。
実は割り込みには優先度があり、NMIによる処理は絶対に1番目に実行され、それ
以外は予め決められているか、自分で決めることが出来ます(但し、自分で決める
場合は相当ハードにも詳しくないといけない為、難易度は高め)。

タイマ割り込み
先ほど2種類あると書きましたが、もう一つ、少し特殊な外部割り込みを書いて
おきます。
その割り込みは「タイマ割り込み」で、これも外部にあるタイマを利用し、CPUが
設定した時間が経つと起こる割り込みです。
タイマ系統はwait関数も使われますが、このタイマ割り込みの方がやはり正確です。
しかも割り込みなので、セットしたらタイマが終了したときにいつでも呼び出せる
のでタイマをセットしつつも動かせる、ということでゲームにもよく使われます。

内部割り込み
CPU内部によって引き起こされる割り込みで「ソフトウェア割り込み」とも呼ばれて
います。この割り込みはゼロ除算やオーバーフロー等の例外による異常、システム
コールに使われています。
この内部割り込みはCPU内にある割り込みを起こす為の命令により発生します。
つまり内部割り込みで言う「割り込み信号」は「CPU内の割り込みを引き起こす為の
命令」ということになります。
割り込みは本来「外部割り込み」のことを示すのでこの「内部割り込み」を
「割り込み」の解説に入れるべきかは怪しいところです(一応「SoftWare Interrupt
(SWI)」と区別して呼ぶこともあるらしいです)。

割り込みの欠点

そんな割り込みにも欠点があります。
それは、使用するハードに依存することです。割り込みハンドラを登録する割り込み
ベクタテーブルに割り当てられているメモリアドレスや割り込みを制御する関数、
外部割り込みの信号線等はハードによって異なるので、ハード毎にそれを理解して
おく必要があります。
また、割り込みハンドラで長い間処理をさせるということはしてはいけません
割り込みハンドラは現在実行していた処理を中断して実行するものだからです。
ループ文を使う等もってのほかです(因みにこの欠点に関しては長い処理はmain関数
に入れ、割り込みハンドラはフラグを立てるだけにしそのフラグが立ったときにその
長い処理を実行させることで解決出来る問題でもある)。


以上です。これで割り込みに関して分からなくとも何か掴めたなら書いた甲斐が
あったなと思います。もし僕の書いていることが間違っていたとしても、それは
それで勉強になるのでありがたいです。

今回はこれくらいにしときます。