---
title: みかん本輪読会_7
tags: 
author: [こた](https://www.docswell.com/user/kota)
site: [Docswell](https://www.docswell.com/)
thumbnail: https://bcdn.docswell.com/page/KJ4M4MRQE1.jpg?width=480
description: みかん本輪読会_7 by こた
published: August 17, 25
canonical: https://www.docswell.com/s/kota/Z8WLPL-mikan-7
---
# Page. 1

![Page Image](https://bcdn.docswell.com/page/KJ4M4MRQE1.jpg)

みかん本輪読会
第7章
割り込みとFIFO


# Page. 2

![Page Image](https://bcdn.docswell.com/page/LE1848QL7G.jpg)

割り込みとは
発生したイベントの種類に応じて通常の計算処理をいったん中断し、
適切な処理を実行すること
内部割り込み → 実行中のプログラムが発生原因となる割り込み
・スーパーバイザコール割り込み/プログラムチェック割り込み
外部割り込み → 内部割り込み以外の要因で発生する割り込み
・入出力割り込み/タイマー割り込み/マシンチェック割り込み/リスタート割り込み


# Page. 3

![Page Image](https://bcdn.docswell.com/page/GEWZXZMQE2.jpg)

イベントとは
CPU内の通常の計算処理以外の事象
CPUが周辺装置などから受け取る
発生するタイミングは前もってわからない
例）
・マウスが移動した
・ネットワークインタフェースにパケットが届いた
・キーボードから文字が入力された
・プログラムを開始した/終了した


# Page. 4

![Page Image](https://bcdn.docswell.com/page/47Z161Q3J3.jpg)

割り込みの実装方法
p.162
ポーリング方式 → OSがイベントが来ているかどうかを確認(6章での実装)
割り込み方式 → イベントが到着した際にハードウェアがOSに通知(本章)
リスト 6.24→
ポーリング方式の問題点
・確認する周期が長いとイベントの発生から検出までが長くなり、ラグが生じる
・確認する周期が短いとCPUの負荷が増え、処理速度に影響が出る


# Page. 5

![Page Image](https://bcdn.docswell.com/page/YJ6L2L6ZEV.jpg)

x86アーキテクチャでの割り込み
p.162~163
事前準備
・イベント発生時に実行する割り込みハンドラ(関数)を準備
・割り込みハンドラをIDT(割り込み記述子テーブル)に登録
イベント発生時
・ハードウェア(場合によってはソフトウェア)がイベントをCPUに通知
・CPUは現在の処理を中断し、イベントの種類に応じて登録された割り込みハ
ンドラに処理を移す
・割り込みハンドラの処理が終わると中断していた処理を再開


# Page. 6

![Page Image](https://bcdn.docswell.com/page/GJ51216974.jpg)

割り込みハンドラ
p.163
・__attribute__((interrupt))
純粋なC++の関数ではなく
割り込みハンドラであることを
コンパイラに伝えている
→ コンパイラが割り込みハン
ドラに必要な前処理、後処理を挿入してくれる
(コンテキストスイッチ 詳しくは13章)
リスト7.1


# Page. 7

![Page Image](https://bcdn.docswell.com/page/LE31K1Q275.jpg)

NotifyEndOfInterrupt()
p.163~164
・NotifyEndOfInterrupt()
レジスタの0xfee000b0番地
に0を書き込む
リスト 7.2
→ 割り込み処理の終了をCPUに伝えることができる
volatile修飾子をつけることで、コンパイルの最適化の対象外となる
→ *end_of_interrupt = 0; は他の場所で利用されないため、最適化されると
値が書き込まれなくなる可能性がある


# Page. 8

![Page Image](https://bcdn.docswell.com/page/8EDX3X96JG.jpg)

割り込みベクタ
p.164
・多種多様な全てのイベントが同じ割り込みとして扱われると不便
→ 割り込みの種類毎に異なる割り込み要因番号、別名割り込みベクタを割り
振って管理する仕組みが必要
・x86アーキテクチャでは0から255のいずれかの数値になる
→ 0除算割り込みでは0が割り当てられている
・CPUはそれぞれの割り込みベクタNに対し、N番の割り込みが発生した時に実
行する割り込みハンドラを知っている必要がある


# Page. 9

![Page Image](https://bcdn.docswell.com/page/V7PP4P9Z78.jpg)

割り込み記述子テーブル (IDT)
・割り込みベクタと割り込みハンドラを対応付けるテーブル ↓
・長さ256の配列で実装
リスト 7.4
p.165


# Page. 10

![Page Image](https://bcdn.docswell.com/page/2JV2X2MMJQ.jpg)

割り込み記述子の構造
p.166
・oﬀset_low、oﬀset_middle、oﬀset_highは割り込みハンドラのアドレスを設定
するフィールド (3つを組み合わせて64bit)
・segment_selectorは割り込みハンドラを実行する際のコードセグメント(実行可
能コードが置いてあるメモリの区間)を指定する
・P、DPL、Type、ISTはattr.bitsというビットフィールドに含まれる
・attrは割り込み記述子
の種別を設定する


# Page. 11

![Page Image](https://bcdn.docswell.com/page/5EGRVRGXJL.jpg)

割り込み記述子の設定
p.168
・IDTの設定が終わったらIDTの場所をCPUに教える必要がある
・LoadIDT()
→ IDTの大きさとIDTが配置されているメインメモリのアドレスを受け取り
lidt命令でCPUに登録
lidt命令は指定したメモリ位置の値を使用して、割り込み記述子テーブル
レジスタを読み込みこむ命令


# Page. 12

![Page Image](https://bcdn.docswell.com/page/4JQV6VX57P.jpg)

MSI割り込み
p.169
・xHCIでは割り込みの発生方法としてPCI規格が定めるMSIを採用
→ メモリバスへの書き込み動作により、割り込みを発生させる
特定のメモリアドレス(32bit)への書き込みにより、割り込みをCPUに通知
・Destination ID
→ 割り込みを通知するCPUコアの番号
・Vector
→ 割り込みベクタ番号を指定


# Page. 13

![Page Image](https://bcdn.docswell.com/page/K74M4M6VJ1.jpg)

割り込みのまとめ
p.170~171
・割り込みを扱うためには、割り込みハンドラ、割り込み記述子、割り込みの発
生源の設定が必要
・割り込みハンドラは __attribute__((interrupt)) をつけ、処理の最後に
End Of Interruptレジスタへの値の書き込みを行う
・割り込み記述子はメインメモリに作成したIDTという配列の1つで、
割り込みハンドラのアドレスや各種属性を設定する
・IDTは長さ256配列で、各要素は0から255の割り込みベクタに対応する
・IDTの先頭アドレス、大きさをlidt命令によりCPUに登録する
・xHCIではMSI方式で割り込みを発生させる


# Page. 14

![Page Image](https://bcdn.docswell.com/page/LJ1848V4EG.jpg)

割り込みハンドラの高速化
・イベントが発生すると
受信したデータの解析 / 関数の呼び出し / メモリの書き込み
等が発生し、時間がかかる
・割り込み処理中は他の割り込み処理を受け付けることが出来ない
→ マウスならまだしもネットワークパケットを取りこぼすと大変
高速化の必要性有り
戦略としては割り込みが来たことだけを記録し、処理は後で行う
p.172


# Page. 15

![Page Image](https://bcdn.docswell.com/page/GJWZXZLZJ2.jpg)

p.172~178
割り込みの記録方法
・割り込みが来た順番を記録するためにFIFOであるキューを使用する
→ メモリ管理が未実装なためC++の標準キューが使えない、自作する
・Message構造体
→ 割り込みハンドラからメイン関数に
対して送信するメッセージを定義
現時点ではxHCIのみなのでtypeは1つ
・割り込みハンドラでやる処理は
構造体の値を生成しキューにプッシュ
リスト 7.15


