コンテンツにスキップ

第8章 システムコール,例外,割り込み

多くの CPU では,分岐命令の他にも「命令流の特別な切り替え」を伴う仕組みが提供されている.
本章では,「命令流の特別な切り替えを伴う事象」である「例外・割り込み系」のうち,「システムコール」,「例外」,「割り込み」について扱う.

8.1 用語の定義

システムコール」,「例外」,「割り込み」の意味は,各社の CPU ごとに異なるが,本章では以下のように定義する.

  • システムコール」:
    • 特権レベルの変更命令によって明示的に発生させる命令流の切り替え
    • CPU のパイプライン上の命令実行ステージで発生する
  • 例外」:
    • 命令実行時に発生するまれなケースをハードウェアで検出した際,暗黙的に発生する命令流の切り替え
    • CPU のパイプラインの各所で発生する
  • 割り込み」:
    • 外部からの要求による命令流の切り替え
    • CPU の外部で発生する

図 8.1 に各事象が CPU のハードウェア構成のどこで発生するかをまとめる.

また,本章における「例外・割込み系」の特徴を表 8.1 にまとめる.
表 8.1 の見方は,

  • 発生要因:
    • 命令:CPU が実行する命令がトリガー(CPU内部での原因)
    • 外部:CPU の外部からの信号やイベントがトリガー
  • 命令で明示:命令で意図的に起こされるか否か
  • 命令と同期:
    • 同期:命令の結果として必ず発生する
    • 非同期:命令とは独立して発生する
  • 命令の完了:発生要因の命令を完了させるか否か
  • 特権レベル変更:事象によって,CPUの権限レベルが切り替わるか否か
事象 発生要因 命令で明示 命令と同期 命令の完了 特権レベル変更
分岐命令 命令  明示 同期 完了 不変
システムコール 命令  明示 同期 完了 変更
例外 命令  暗黙 同期 不可 変更
割り込み 外部  - - - 変更

表 8.1 命令流の切り替えを伴う事象の分類

8.2 システムコールとその利用シーン

本章におけるシステムコールとは,前述のとおり,特権レベルの変更命令によって明示的に発生させる命令流の切り替え事象である.そのための命令を「システムコール命令」と呼ぶ.

8.2.1 特権レベル

特権レベルとは,ハードウェア資源へのアクセス権限を段階的に制限するための仕組みである.
少なくとも次の 2 つの状態に相当するものが特権レベルとして用意され,CPU はいずれかの状態に置かれる.

  • ユーザーレベル:アクセス制限が最も厳しいレベル
  • スーパーバイザレベル:資源への広いアクセスが許可されているレベル

ユーザーレベルから,より広い権限のスーパーバイザレベルなどへの変更を明示的に行うのがシステムコールであり,その際に命令流の切り替えが発生する.

8.2.2 システムコールの発生方法

システムコールは,各 CPU で提供されている専用のシステムコール命令によって発生する.これにより,特権レベルを変更するとともに,定められた命令流(8.5節で解説する「ハンドラ」)に切り替える.
ハンドラから元のソフトウェアに戻り,かつ特権レベルを元のソフトウェアのレベルに戻すためには,戻り専用の命令を実行する.
代表的な CPU におけるシステムコール命令及びユーザーソフトウェアなどへ戻るための命令を表 8.4 に示す.
表 8.4 を補足する(長くなるので Arm v8 AArch64 のみ記載).

  • SVC (Supervisor Call):ユーザープログラム(EL0)がOSカーネル(EL1)にサービスを要求するための命令でシステムコールの実装に使われる
  • HVC (Hypervisor Call):OSカーネル(EL1)がハイパーバイザー(EL2)にサービスを要求するための命令で仮想化環境で利用される
  • SMC (Secure Monitor Call):ノーマルワールドからセキュアワールド(EL3)へサービスを要求するための命令でセキュリティ機構やファームウェアとの連携に使われる
  • ERET (Exception Return):割り込みや例外ハンドラから元の実行状態に戻るための命令.復帰先アドレスやCPU状態は専用レジスタ(ELR, SPSR)に保存されている
命令 Arm v8 AArch64 RISC-V Intel/AMD x86
システムコール svc や hvc や smc ecall int や sysenter や syscall
戻り eret sret,mret iret や sysexit や sysret

表 8.4 各 CPU のシステムコール系命令

8.2.3 システムコールとその利用シーン

ソフトウェアは,特権レベルに基づいて階層的に構成することで,異常の局所化や安全性の向上や資源利用の効率化などを図れる.この階層間の遷移を実現するのがシステムコールである.一般には,ユーザーソフトウェアにおいてシステムコール命令を直接的に記述するのではなく,各種ライブラリを介してシステムコール命令を利用する
汎用 OS(Windouws,macOS など)を用いるシステムでは,ユーザーソフトウェアから OS の機能を要求するためにシステムコールが用いられる.具体的には以下ような場合にシステムコールが用いられる.

  • I/O デバイスへのアクセス要求
  • メモリ領域の割り当て要求

8.3 例外とその利用シーン

本章における例外とは,前述のとおり,命令実行時に発生する稀なケースをハードウェアで検出した際,暗黙的に命令流が切り替わる事象を指す.
「稀なケース」としては,命令を正常に実行できない状況や,命令を完了させてはいけない状況がある.具体的は,以下のような場合である.

  • ゼロによる除算
  • 権限のない資源へのアクセス違反

こうした命令を続行できない状況をハードウェアで検出して命令流を切り替えることで,ソフトウェアによる頻繁なチェックの必要性や漏れを回避しつつ,異常や特別な状態が生じてもシステムを健全に保てるようにする.

8.3.1 例外の発生方法

例外は,命令実行時にハードウェアが特定の条件を検出することによって発生する.どのような条件により例外が発生するかは CPU によって異なる.
代表的な例外の要因を表 8.5 に示す.
表 8.5 を補足する.

  • アライメント違反:メモリ上のデータ配置に関する制約を守らずにアクセスした場合に発生
  • ページフォールト:プログラムがアクセスしようとした仮想メモリのページが物理メモリ上に存在しない場合に発生
  • アクセス異常:プログラムが許可されていないメモリ領域にアクセスしようとしたときに発生
大まかな種別 例外要因
命令種別関連 未定義命令,命令権限違反,など
演算関連 ゼロ除算,浮動小数点演算,など
メモリ,仮想記憶関連 アライメント違反,ページフォールト,アクセス異常,など

表 8.5 主な例外の要因

8.3.2 例外とその利用シーン

例外の主な利用シーンは,命令実行時の異常な状態もしくは特別な場合の検出である.
命令実行時の異常な状態とは,ソフトウェアにおける想定外の状態を指す.これを検出した場合の対処は,切り替え先の命令流として記述される.
命令実行の特別な場合とは,稀な事象ではあるがソフトウェアシステムとしては想定内の状態を指す. 一例としては,仮想記憶におけるページフォールトがある.例えば OS の実装においては,該当のページが主記憶上にない場合を検出するのにページフォールト例外を利用する. これにより,そのページが必要になったらすぐに二次記憶から主記憶にコピーする「デマンドページング」を実現している.また,該当ページへの最初の書き込みを検出するのにもページフォールト例外を利用している.これにより,専用の物理メモリが必要になったらすぐに割り当てる「コピーオンライト」を実現している.
例外は,一般に OS などのシステムレベルのソフトウェアが処理する.ただし,発生元のソフトウェアに例外を通知する仕組みが設けられているシステムもある.そのような仕組みがある場合は,例外発生時の処理をユーザーソフトウェアに置いて記述することが可能になる.

8.4 割り込みとその利用シーン

本章における割り込みとは,前述のとおり,外部からの要求における命令流の切り替え事象を指す.システムコール及び例外とは異なり,CPU における命令実行に直接起因する事象ではない.
割り込みによって,命令流に対して非同期に発生するさまざまな事象を素早くかつ効率的に扱える.これによりイベント駆動のソフトウェアシステムを構築できる.

8.4.1 割り込みの発生方法

図 8.2 に示すように,割り込みを使用するためには,一般に,

  1. CPU 外部の割り込み要求元
  2. その要求を束ねる割り込みコントローラ
  3. そして割り込み要求を処理する CPU

のそれぞれを適切に設定する必要がある.

(1)割り込み要求元は,割り込みをする条件や,そもそも割り込み要求を行うか否かなどを設定する.多くの場合,割り込み要求元となるのは I/O デバイスである.I/O デバイスの割り込み設定は,CPU からの I/O ライトアクセスによって行う.

補足
I/O ライトアクセス:コンピュータが外部機器(ストレージや周辺機器など)に対してデータを書き込む(出力する)操作のこと
I/O デバイスの割り込み設定は,CPU からの I/O ライトアクセスによって行う:CPU が I/O デバイスの制御用レジスタ(またはデバイスファイル)にデータを書き込むことで,割り込みの許可・禁止や制御を行う

(2)割り込みコントローラは,複数の割り込み要求元からの割り込み要求を CPU に伝える優先度などを設定する.この中間階層が,CPU および割り込み要求元となることが多い I/O デバイスからしている独立していることにより,多様なシステムが構築可能となる.CPU から見ると,割り込みコントローラも I/O デバイスの一つであるので,割り込みコントローラの設定も CPU からの I/O ライトアクセスにより行う.

(3)割り込みを受け付ける側の CPU については,割り込み発生時に命令流をどのアドレスへ切り替えるかや,そもそも割り込みを受け付けるか否かなどを設定する.

割り込みの設定は煩雑なものになるが,通常,その多くの部分は OS やライブラリの層によって隠蔽されている.

8.4.2 割り込みの利用シーン

割り込みは,主に CPU 外部で発生するイベントに応じて非同期に処理を行うシステムに用いられる.
割り込みはいつ発生するかわからない事象だが,割り込みの要求元や割り込み処理用の制御回路などはシステムの共有資源であり,かつ発生した場合の優先度が高い事象である.そのため,複数の割り込み要求が多重に発生した場合の優先度や,発生頻度の調整,割り込む先のソフトウェアへの性能影響など,その適切な利用にあたってはシステム観点での設計が必要になる.

8.5 例外・割り込み系の振る舞い

システムコール,例外,割り込みは,利用シーンや用途こそ異なるが,いずれも命令流の特別な切り替えを伴う事象であることから,CPU のパイプラインにおける挙動としてはよく似ている.具体的には,図 8.3 に示すように,いずれも事象の発生時に CPU ハードウェアが自動的に PC レジスタを変更し,新しい命令流のための命令フェッチを開始する.

PC レジスタの変更によって命令流の切り替えを行うという点に関しては,分岐命令とも共通している.ただし,分岐先のアドレスを事象の発生源では明示しないこと,また,CPU の特権レベルが変更されるという点が異なる.
切り替え先の命令列は,一般に「ハンドラ」都呼ばれる.それぞれの事象に合わせて,「システムコールハンドラ」,「例外ハンドラ」,「割り込みハンドラ」と呼ぶこともある.
以降では,切り替え先の命令アドレスの選び方,CPU の状態変更,戻り先の保存,切り替え後の振る舞いについて説明する.

8.5.1 切り替え先のアドレスについて

命令流を切り替えるには,切り替え先となる命令のアドレスが必要である.このアドレスは,ユーザーソフトウェアでは指定できず,システムソフトウェアが用意した「ベクタテーブル」と呼ばれるテーブルから供給される.ベクタテーブルは,書き換え可能なテーブルとして,一般にはメモリ上に格納されている.
図 8.4 に,ベクタテーブルとハンドラ,および命令流の切り替えの関係を示す.

命令流の切り替えは以下のフローで行われる.

  1. まず切り替え先となる命令アドレス(ハンドラの先頭アドレス)がベクタテーブルからロード
  2. その値を用いて PC レジスタが変更
  3. 変更された PC レジスタに基づいて,新たな命令フェッチが開始

8.5.2 CPU の特権状態の変更

システムコール,例外,割り込みにおける命令流の切り替え時には,一般に CPU の特権レベルも変更される.多くの場合には,ユーザーレベルからスーパーバイザレベルへと遷移する.図 8.3 の例では,システムコール命令の実行完了を境界として,特権レベルをユーザーレベルからハイパーバイザレベルに切り替えている.

8.5.3 戻り先やコンテキストの保存

システムコール,例外,割り込みによる命令流の切り替えは,一時的な命令流の切り替えである.切り替え先の命令流(ハンドラ)における所定の処理が終わったら,一般的には元のソフトウェアの命令流へ戻る.そのために,<事象発生による命令流の切り替え時点で,(1)戻り先となる命令のアドレス(2)コンテキスト(特権レベルやレジスタの値)を特別なレジスタに保存しておく.

(1)戻り先となるアドレスの保存は,一般には CPU ハードウェアで自動的に行う.また,戻り先として保存されるアドレスは事象に応じて異なる.

  • システムコールの場合:

    • 完了後に次の命令から継続させる必要がある
    • 次の命令のアドレスが戻り先として保存される
  • 例外の場合:

    • 例外ハンドラにおいて適切な処理ができた場合:
      • 例外を発生された命令から再実行させる必要がある
      • 例外を発生させた命令のアドレスが戻り先として保存されることが多い
    • 例外ハンドラにおいて適切な処理ができなかった場合:
      • プログラムの終了など
  • 割り込みの場合:

    • 現在の命令流における@命令と命令の間」に割り込み処理なので,割り込まれた命令のアドレスが戻り先として保存される

(2)事象発生時の特権レベルも,多くの CPU では命令流の切り替え時にハードウェアによって専用のレジスタへ保存される.
(2)レジスタの値の内容については,必要に応じてハンドラ内のソフトウェアが保存するのが一般的だが,ハードウェアによっては自動的に保存される CPU もある.

8.5.4 命令流の切り替え後の振る舞い

  • システムコール命令の場合:システムコールハンドラのソフトウェアの記述内容次第で変わる

    • 汎用レジスタやシステムコール命令オペランドを用いて,システムコールで要求する処理をシステムコールハンドラに伝える
  • 例外の場合:発生時に CPU のパイプライン上の命令を完了させてはいけないので,該当の命令による作用をすべてキャンセルする必要がある

    • アウトオブオーダー実行の CPU の場合には,命令順序を元に戻すリオーダーなどの仕組みが必要になる
  • 割り込みの場合:命令流側から見るといつ発生するかわからないので,ソフトウェアにおけるアトミックな操作を中断しないようにする必要がある

    • アトミックな操作の最中は一時的に割り込みを禁止にすることで実現できるが,システム全体の応答性が劣化する可能性があるので注意が必要

8.6 例外・割り込み系が CPU の動作を遅くする背景

システムコール,例外,割り込みは,通常は発生頻度が低い事象だが,一回当たりの性能ダメージは分岐命令よりも大きくなる傾向にある.疎の遅さの主な要因は,次の二つに大分できる.

  • 命令流の切り替え操作に伴い,CPU のパイプラインで無駄な空きサイクルが生じる
  • 切り替え先の命令流(ハンドラ)内の実行命令が遅い可能性がある

8.6.1 分岐予測が効かない

以下の理由から,システムコール,例外,割り込みによる命令流の切り替えは,一般に分岐予測の対象とはしない.従って,予測に基づく先行的な命令フェッチによって命令流の切り替えの遅さを改善することはできない.

  • システムコール:

    • 命令によって必ず命令流を切り替える事象であることから,原理的には分岐予測の対象にできる
    • しかし,システムコールの分岐予測はバグやセキュリティ上の課題を誘発するので,一般に CPU ハードウェアへの実装は慎重である
  • 例外:

    • 多くの種類の命令によって引き起こされる可能性があるため,そのすべてを分岐予測の対象にすると,分岐予測のための資源容量を圧迫してしまう
    • 発生頻度が低いので,予測しても有利にはならない
  • 割り込み:

    • 現在の PC レジスタとは無関係に発生する事象であるので,分岐予測の基本的な機構(現在の PC レジスタの値を登録済みの命令アドレスと比較する)になじまない

8.6.2 特権レベルの変更前後は逐次的な実行が必要

(1)特権レベルの変更は,事象の発生点に先行する命令に影響してはならない一方で,事象の発生点より後続の命令では確実に反映される必要がある.そのため,事象の発生点の前後ではアウトオブオーダー実行による命令順序の入れ替えを行わない.
また,(2)事象の発生点より後続の命令に対する命令フェッチ操作において新しい特権レベルが反映されるように,命令流の切り替え境界ではパイプラインを一旦空にする必要がある(パイプラインフラッシュ).
(1),(2)をもう少し視覚的に説明してみる.

1
2
3
4
(1)に関して,もし事象の発生点の前後でアウトオブオーダー実行をしてしまうと

[ユーザーモード命令A] → [特権変更命令B] → [カーネルモード命令C]
      ↑(AとCが順序入れ替えで実行されると…)

1
2
3
4
5
6
7
(2)に関して,命令流の切り替え教会でパイプラインフラッシュをしないと

パイプライン
| A | B | C | D | E |
      ↑
   特権変更
(B以降の命令が古い特権レベルでフェッチされているので,一旦空にする必要がある)

このように,特権レベルの変更層座の前後では一般に完全な逐次化が行われる.そのため,命令を実行できない無駄なサイクルが生じる.

8.6.3 ベクタテーブルのアクセスにおけるキャッシュミス

ベクタテーブルはメモリ上に配置される.システムコール,例外,割り込みは稀な現象であるので,キャッシュミスが起こりやすい.

8.6.4 ハンドラ内での分岐予測ミス,キャッシュミス,TLB ミス

システムコール,例外,割り込みは稀な現象であるので,切り替え先のハンドラの命令列もまれにしか実行されない.従って,ハンドラ内では分岐予測ミスやキャッシュミス,TLB ミスが発生しやすい.

8.6.5 ハンドラからの戻りも必要

ハンドラ切り替える際と同様に,にハンドラから戻るための命令も一般に分岐予測の対象としないうえ,一般に逐次化のための順序付けとパイプラインフラッシュを伴う.

8.7 ソフトウェアによる対策

命令流の特別な切り替えは,頻度が低い字事象であることから,分岐命令やキャッシュミス戸倉bると対策の優先度は低いといえる.その一方で,これが課題となる場合にはシステムレベルでの検討が必要な可能性があるという難点がある.また,各社の CPU によって大きな差異がある部分でもあり,かつ応用が多岐にわたる仕組みなので,各社の CPU に共通する対策が難しいという面もある.ここでは一般的な観点に絞ってソフトウェア的な対策を簡単に紹介する.

8.7.1 システムコール

  • 明示的な命令によって発生するためソフトウェアによる制御が比較的しやすい
  • 対策:発生頻度を適切に抑える

8.7.2 例外

  • 命令に付随して暗黙的に発生するため対策が比較的難しい
  • 発生頻度の低さなどの理由から性能ダメージは小さいと割り切ってもいい

8.7.3 割り込み

  • システムの共有資源を利用し,かつ発生するタイミングがわからない優先度の高い事象のため対策が特に難しい
  • 対策:割り込みの発生回数を減らす(応答性とのトレードオフ)

8.8 システムコール,例外,割り込みについての実験

8.8.1 システムコールの実行例

CPU におけるシステムコールの実行方法は単純で,OS の使用において定められたレジスタに値を設定したのち,システムコール実行用の命令を呼び出すだけである.システムコール実行用の命令は CPU によって異なる(表 8.4 を参照).
システムコールを伴うシンプルなプログラム例として,Linux における write システムコールの使用例を紹介する.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
/*
 * System-call example for x86/Linux
 *
 *   * write(2) system-call
 *   * see: man 2 write
 *   * see: linux-kernel's arch/x86/entry/syscalls/syscall_64.tbl
 *   * see: x86-64 ABI (https://gitlab.com/x86-psABIs/x86-64-ABI)
 */

        .intel_syntax noprefix
        .global main

main:
        sub     rsp, 8                  /* 16-byte alignment */


        /* write(2) system-call */
        mov     eax, 1                  /* システムコール番号 1(writeシステムコール)を指定 */
        mov     edi, 1                  /* write の第 1 引数(出力先は標準出力)*/
        lea     rsi, [rip + msg]        /* write の第 2 引数(出力データは msg で定義する文字列 ) */
        mov     edx, 13                 /* write の第 3 引数(出力数は 13 文字) */
        syscall                         /* システムコールを実行 */


        /* return from main */
        add     rsp, 8                  /* 16-byte alignment */
        ret


        /* read-only data */
        .section .rodata
msg:
        .string "hello, world\n"        /* write システムコールに渡す文字列 */

write システムコールは,指定する出力先に,指定するアドレスからのデータを,指定するバイト数だけ出力するというものである.
x86 用の Linux では rdi,rsi,rdx などのレジスタを用いる.
実行結果は以下のようになる.

1
2
hytn@amanohashidate:~/cpu-assembly-examples/x86/linux$ ./syscall_write 
hello, world

システムコールが実行されると,特権レベルが変更されるとともに,システムコールハンドラへと命令流が切り替わる.システムコールハンドラにおいてどのような処理が行われるかは OS やシステムに依存する.
通常,ユーザーのプログラムでシステムコールを直接利用することは少なく,ライブラリやプログラミング言語の処理系がシステムコールの実行を隠蔽している.たとえば,C 言語用のmライブラリ関数である printf や puts は,内部で write システムコールを実行している.

8.8.2 例外(ページフォールト)の発生例

メモリアクセスにおけるページフォールト例外を発生させるプログラムの例を示す.
このプログラムでは,mov 命令によってメモリの 0 番地からのロードを行っているだけである.
Linux では一般的に仮想アドレスの 0 番地を物理アドレスに対応付けていないため,0 番地へのアクセス時にはページフォールト例外が発生する.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
/*
 * Exception example for x86/Linux
 *
 *   * Page fault exception
 *
 */

        .intel_syntax noprefix
        .global main

main:
        mov     rdx, 0                  /* アクセスアドレスとして 0 番地を用意
        mov     rax, [rdx]              /* メモリアクセスの実行.この命令で例外が発生する */

        ret

実行結果は以下のようになる.

1
2
hytn@amanohashidate:~/cpu-assembly-examples/x86/linux$ ./excep_load
Segmentation fault (core dumped)

8.8.3 発生する割り込みを確認する

プログラムの視点では,割り込みはいつどこで発生するかがわからないものである.
こうした性質から,割り込みについてはユーザーレベルでのみ如何察する短い実験用プログラムを紹介しにくいという難点がある.そこで本節では,特定の CPU や割り込みコントローラを想定した具体的なプログラム例ではなく,簡単なコマンドを用いて Linux における割り込みの要因と頻度を概観してみる.

Linux では,システムの起動時からの割り込み発生回数が /proc/interrupts ファイルに記録されている.cat コマンドを用いて /proc/interrupts の内容を表示することで,どのような要因による割り込みがどの程度発生しているかを知ることができる.
実行結果の見方を示す.

  • 一番左の列(もしくは NMI などのシンボル)は割り込み要因ごとに割り当てられた識別子(IRQ 番号)
    • x86 用の Linux では,0 から 31 はシステム関連,32 から 127 はデバイス関連,LOC 以降は特別な割り込みに割り当てられている
  • 左から二番目から右から四番目の各列は各CPUコアでの割り込み回数を表示
  • 右から三番目の列は割り込みコントローラー
  • 右から二番目の列は割り込みタイプ
  • 右から一番目の列はデバイス名/割り込みソース名
実行結果
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
hytn@amanohashidate:~/cpu-assembly-examples/x86/linux$ cat /proc/interrupts
            CPU0       CPU1       CPU2       CPU3       CPU4       CPU5       CPU6       CPU7       CPU8       CPU9       CPU10      CPU11      CPU12      CPU13      CPU14      CPU15      CPU16      CPU17      CPU18      CPU19      CPU20      CPU21      CPU22      CPU23      
   0:         38          0          0          0          0          0          0          0          0          0          0          0          0          0          0          0          0          0          0          0          0          0          0          0  IR-IO-APIC    2-edge      timer
   8:          0          0          0          0          0          0          0          0          0          0          0          0          0          0          0          0          0          0          0          0          0          0          0          0  IR-IO-APIC    8-edge      rtc0
   9:          0   30429540          0          0          0          0          0          0          0          0          0          0          0          0          0          0          0          0          0          0          0          0          0          0  IR-IO-APIC    9-fasteoi   acpi
  18:          0          0          0          0          0          0          0          0          0         74          0          0          0          0          0          0          0          0          0          0          0          0          0          0  IR-IO-APIC   18-fasteoi   ehci_hcd:usb1, ehci_hcd:usb2, i801_smbus
  25:          0          0          0          0          0          0          0          0          0          0          0          0          0          0          0          0          0          0          0          0          0          0          0          0  IR-PCI-MSI-0000:00:01.0    0-edge      PCIe PME
  27:          0          0          0          0          0          0          0          0          0          0          0          0          0          0          0          0          0          0          0          0          0          0          0          0  IR-PCI-MSI-0000:00:02.0    0-edge      PCIe PME
  29:          0          0          0          0          0          0          0          0          0          0          0          0          0          0          0          0          0          0          0          0          0          0          0          0  IR-PCI-MSI-0000:00:03.0    0-edge      PCIe PME
  30:          0          0          0          0          0          0          0          0          0          0          0          0          0          0          0          0          0          0          0          0          0          0          0          0  IR-PCI-MSI-0000:00:1c.0    0-edge      PCIe PME
  31:          0          0          0          0          0          0          0          0          0          0          0          0          0          0          0          0          0          0          0          0          0          0          0          0  IR-PCI-MSI-0000:00:1c.2    0-edge      PCIe PME
  32:          0          0          0          0          0          0          0          0          0          0          0          0          0          0          0          0          0          0          0          0          0          0          0          0  IR-PCI-MSI-0000:00:1c.4    0-edge      PCIe PME
    (中略)
    137:    2848701    4168377   24759654   39837700    2869216    2568177    5705425    3398406   18561273    4219563    4030344   18101902    3751552    3418278    5212325    1765445    2530831    3476793   28416831   19904625   15711589    3336470   12261601   15851023  IR-PCI-MSIX-0000:01:00.1   22-edge      mlx5_comp21@pci:0000:01:00.1
 138:    2106529   26454474   17664690   11199593   28336573    3590174    3724771   10993705    2219464    6707570   26350386    6568630    5274641    3688972   17761987    2449480    2743860   41922445    8433629  732293135   20457623    4805870   10990411    4755155  IR-PCI-MSIX-0000:01:00.1   23-edge      mlx5_comp22@pci:0000:01:00.1
 139:    7163971   25703791    4002174    5564953    2242728    2802141   37216318    2867658    2073454    3868779   10679031    4071005    3968424    3279137    5654719    2030457    2628007    2253909   13692444    4466713    2156200    4504980   12767023    3046147  IR-PCI-MSIX-0000:01:00.1   24-edge      mlx5_comp23@pci:0000:01:00.1
 NMI:     182638     160284     157999     145094     147218     146310     143827     144874     143180     146312     144833     139706     144248     148544     155826     145809     147762     151891     158309     161290     152553     160840     160730     183761   Non-maskable interrupts
 LOC: 2566777709  673675594  354297720  172236034  151529702  129115341  118461986   80034374   52025970   63847675  607841389 4275503975   13938425  110692123  167103134   87510049   94463450  135501017  194617044  216473855  110377481  168522654  209247210  369377861   Local timer interrupts
 SPU:          0          0          0          0          0          0          0          0          0          0          0          0          0          0          0          0          0          0          0          0          0          0          0          0   Spurious interrupts
 PMI:     182638     160284     157999     145094     147218     146310     143827     144874     143180     146312     144833     139706     144248     148544     155826     145809     147762     151891     158309     161290     152553     160840     160730     183761   Performance monitoring interrupts
 IWI:      16000      51865      54363      16181      19697      21613      24963      28849      13868      40715      49836      34845      39139      40624      62018      14824      17708      19246      21924      30034      15014      42536      57934      32193   IRQ work interrupts
 RTR:          0          0          0          0          0          0          0          0          0          0          0          0          0          0          0          0          0          0          0          0          0          0          0          0   APIC ICR read retries
 RES:   16021481   14001799   15239874   13486501   13410385   13333242   13582291   13379862   13320711   13747505   13642381   13785083   13641288   14050330   14049844   13925875   13791338   13957021   13923865   15068281   14047309   14572287   14354362   13951245   Rescheduling interrupts
 CAL:  838287013  404850783  301391924  261363292  246350217  238235286  235543888  231229881  225045485  226513044  229601649  223137365  224990984  224230011  223812895  220320475  220392647  219366744  217691453  218497050  214150071  214871066  218373889  213169878   Function call interrupts
 TLB:  100220444   99232457   99280510   97639538   97275665   96898637   96974527   96737927   96883196   97111666  101760877   96908180   90990232   94472160   95686893   96503682   96574543   96374204   96834230   96691853   96715416   96850593   97180210   96698167   TLB shootdowns
 TRM:          0          0          0          0          0          0          0          0          0          0          0          0          0          0          0          0          0          0          0          0          0          0          0          0   Thermal event interrupts
 THR:          0          0          0          0          0          0          0          0          0          0          0          0          0          0          0          0          0          0          0          0          0          0          0          0   Threshold APIC interrupts
 DFR:          0          0          0          0          0          0          0          0          0          0          0          0          0          0          0          0          0          0          0          0          0          0          0          0   Deferred Error APIC interrupts
 MCE:          0          0          0          0          0          0          0          0          0          0          0          0          0          0          0          0          0          0          0          0          0          0          0          0   Machine check exceptions
 MCP:      45328      45329      45329      45329      45329      45329      45329      45329      45329      45329      45329      45329      45329      45329      45329      45329      45329      45329      45329      45329      45329      45329      45329      45329   Machine check polls
 ERR:          0
 MIS:          0
 PIN:          0          0          0          0          0          0          0          0          0          0          0          0          0          0          0          0          0          0          0          0          0          0          0          0   Posted-interrupt notification event
 NPI:          0          0          0          0          0          0          0          0          0          0          0          0          0          0          0          0          0          0          0          0          0          0          0          0   Nested posted-interrupt event
 PIW:          0          0          0          0          0          0          0          0          0          0          0          0          0          0          0          0          0          0          0          0          0          0          0          0   Posted-interrupt wakeup event
hytn@amanohashidate:~/cpu-assembly-examples/x86/linux$ 

続いて,発生する割り込みの要因ごとの頻度を確認する.何らかの操作の前後における /proc/interrupts の内容を比較することで,その操作においてどんな要因の割り込みが何回発生したかを大まかに知ることができる.

実験結果
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
hytn@amanohashidate:~/cpu-assembly-examples/x86/linux$ cat /proc/interrupts > int1
hytn@amanohashidate:~/cpu-assembly-examples/x86/linux$ cursor syscall_write.S 
hytn@amanohashidate:~/cpu-assembly-examples/x86/linux$ cursor ecep_load.S
hytn@amanohashidate:~/cpu-assembly-examples/x86/linux$ rm ecep_load.S 
hytn@amanohashidate:~/cpu-assembly-examples/x86/linux$ cat /proc/interrupts > int2
hytn@amanohashidate:~/cpu-assembly-examples/x86/linux$ diff int1 int2
4c4
<    9:          0   30433067          0          0          0          0          0          0          0          0          0          0          0          0          0          0          0          0          0          0          0          0          0          0  IR-IO-APIC    9-fasteoi   acpi
---
>    9:          0   30433298          0          0          0          0          0          0          0          0          0          0          0          0          0          0          0          0          0          0          0          0          0          0  IR-IO-APIC    9-fasteoi   acpi
16,19c16,19
<   44:      86175     272750     292980     215380     257824     340585     324320     309575     240235     381220     297945     476550     294895     179375     423860     204430     311125     279965     324975     383415     236170     459260     451514     382805  IR-PCI-MSIX-0000:07:00.0    1-edge      eno1-TxRx-0
<   45:      84895     275315     311754     217325     210805     296745     326175     353639     228040     365285     320040     474445     307570     195395     435890     239655     265710     263170     312195     386730     251935     436070     463815     404730  IR-PCI-MSIX-0000:07:00.0    2-edge      eno1-TxRx-1
<   46:      73325     302545     333355     220774     204980     322735     319885     307555     212860     396785     313835     454965     336355     212345     432610     185045     255800     227785     307654     393485     234125     521360     484655     372510  IR-PCI-MSIX-0000:07:00.0    3-edge      eno1-TxRx-2
<   47:      71825     300135     346605     175045     231339     276450     318905     321075     196980     387520     331605     461110     326385     199125     554770     189460     264295     269710     295209     375085     211960     466980     489555     366200  IR-PCI-MSIX-0000:07:00.0    4-edge      eno1-TxRx-3
---
>   44:      86175     272750     292980     215380     257878     340585     324320     309575     240235     381220     297945     476550     294895     179375     423860     204430     311125     279965     324975     383415     236170     459260     451514     382805  IR-PCI-MSIX-0000:07:00.0    1-edge      eno1-TxRx-0
>   45:      84895     275315     311754     217325     210805     296745     326175     353693     228040     365285     320040     474445     307570     195395     435890     239655     265710     263170     312195     386730     251935     436070     463815     404730  IR-PCI-MSIX-0000:07:00.0    2-edge      eno1-TxRx-1
>   46:      73325     302545     333355     220774     204980     322745     319885     307555     212860     396785     313835     454965     336355     212345     432610     185045     255800     227785     307680     393485     234143     521360     484655     372510  IR-PCI-MSIX-0000:07:00.0    3-edge      eno1-TxRx-2
>   47:      71825     300135     346605     175045     231339     276450     318905     321075     196980     387520     331605     461110     326385     199125     554770     189460     264295     269710     295235     375085     211960     467008     489555     366200  IR-PCI-MSIX-0000:07:00.0    4-edge      eno1-TxRx-3
21,24c21,24
<   49:      80440     329995     366125     202855     199980     270789     319255     307080     170900     412210     340265     447390     347769     213535     478655     194445     258240     223755     276245     373310     196250     513160     525440     379240  IR-PCI-MSIX-0000:07:00.0    5-edge      eno1-TxRx-4
<   50:      66855     232280     228950     321175     284370     344225     357090     328575     271134     359449     271360     400545     277125     148110     301230     295725     345400     339945     329265     404015     315400     416095     393940     395070  IR-PCI-MSIX-0000:07:00.0    6-edge      eno1-TxRx-5
<   51:      64645     237705     244390     251385     266630     341905     351645     326010     253154     360775     294289     430590     255965     156565     426780     254395     337510     305280     352470     405810     312305     415655     407960     373510  IR-PCI-MSIX-0000:07:00.0    7-edge      eno1-TxRx-6
<   52:      66530     244865     276505     271860     247470     314800     352285     371315     259399     355880     282715     436905     284085     181274     348625     280820     304515     302295     306105     414805     272965     421015     434025     396270  IR-PCI-MSIX-0000:07:00.0    8-edge      eno1-TxRx-7
・
・
(中略)
・
・
>  RES:   16022157   14002401   15240528   13487063   13410980   13333915   13582940   13380448   13321238   13748188   13642976   13785732   13641861   14051111   14050397   13926518   13791944   13957569   13924443   15068938   14047986   14572878   14354941   13951908   Rescheduling interrupts
>  CAL:  838397949  404907445  301431317  261399075  246383665  238267040  235575786  231262464  225076138  226544413  229633092  223168056  225023206  224264176  223844610  220354662  220426759  219397255  217722164  218528117  214178684  214902716  218405011  213201249   Function call interrupts
>  TLB:  100225457   99236839   99285348   97643555   97279886   96902316   96979468   96742163   96886927   97115539  101765544   96912057   90993934   94476337   95690770   96508119   96578440   96377335   96838109   96695446   96718461   96854189   97183986   96702178   TLB shootdowns
122c122
<  MCP:      45333      45334      45334      45334      45334      45334      45334      45334      45334      45334      45334      45334      45334      45334      45334      45334      45334      45334      45334      45334      45334      45334      45334      45334   Machine check polls
---
>  MCP:      45334      45335      45335      45335      45335      45335      45335      45335      45335      45335      45335      45335      45335      45335      45335      45335      45335      45335      45335      45335      45335      45335      45335      45335   Machine check polls
hytn@amanohashidate:~/cpu-assembly-examples/x86/linux$ 

cat コマンド間の操作内容によっては,わずか数十秒程度の間に,数十~数千回の割り込みが発生していることもある.

8.9 本章のまとめ

本節では,命令流の特別な切り替えを伴うシステムコール,例外,割り込みについて概説した.これらの命令流の特別な切り替えに伴う仕組みは,各 CPU のハードウェア使用に強く依存しており,それだけ扱いが難しいものである.しかし,これらの命令流の特別な切り替えを伴う仕組みの存在により,特権レベルに基づく保護と異常検出を活用した安全なシステム構築をはじめ,効率的な仮想記憶システムやイベント駆動システムなどの高度なソフトウェアが実現可能になる.
一方で,命令流の特別な切り替えは,CPU におけるソフトウェアの実行を遅くする要因の 1 つにもなる.ただし,これらは比較的発生する頻度が低い事象であるため,他の要因に比べると対策が必要な場面は少ない傾向にある.
もし対策が必要になる場合は,個々のソフトウェア単位ではなく,システムレベルでの挙動についての検討が必要となる可能性がある.