割り込みと例外

オペレーティングシステムにおける割り込みと例外について学習したため、そのまとめとしてここに整理する。

Intelプロセッサにおける割り込みと例外

  • 割り込みは2種類に分類できる
    • 同期割り込み
      • CPU内の制御回路により生成される
      • 実行中の命令終了時にのみ発生
    • 非同期割り込み
      • クロック信号に合わせて、CPU以外のデバイスが生成する
  • Intelプロセッサでは、同期割り込みのことを例外、非同期割り込みのことを割り込みと呼ぶ

IRQ (Interrupt Requests)

  • 割り込み生成可能なハードウェアコントローラから送出される信号
  • ハードウェアコントローラはIRQラインと呼ばれるラインを持っており、IRQラインはプログラマブル割り込みコントローラと呼ばれるハードウェア回路に接続されている

割り込みディスクリプタテーブル

  • 割り込みや例外のベクタとハンドラの対応を管理するテーブル
  • GDTとLDTの構造とほぼ同じ

メモリのページングについて

メモリのページングについて学習したため、そのまとめとしてここに整理する。


ページング

  • メモリをページという単位に分割し管理、仮想的なアドレス(仮想アドレス)を割り当てる
  • ページ単位でストレージに退避させることにより、実メモリのサイズよりも大きな領域を取り扱うことを可能とする

仮想アドレス

  • 物理メモリに変換するためのテーブルのエントリに関する情報を持つ
  • ディレクトリ (22 ~ 31bit)
  • テーブル (12 ~ 21bit)
    • ページテーブル内の該当するエントリを指す
  • オフセット (0 ~ 11bit)
    • 割り当てるページフレーム内の相対位置を指す

ページ

  • 仮想アドレス空間を一定サイズで分割し取り扱う単位
  • 1ページあたり4KB

ページフレーム

  • 実メモリを固定サイズで分割し取り扱う単位
  • 物理ページと呼ぶこともあり
  • ページをメモリに配置する枠
  • ページと同じサイズ (4KB)

ページテーブル

  • ページに割り当てられた仮想アドレスから、実際の物理メモリに変換するためのデータ構造
  • メインメモリに配置され、CPUのページング回路を有効にする際にカーネルによって初期化される
  • 最大で1024個のページへのエントリを保持する

ページディレクト

  • ページテーブルと同じ構造をしており、1つのページテーブルを指す
  • 最大で1024個のページテーブルへのエントリを保持する

仮想アドレスから物理アドレスへの変換

  • 2段階に分けて変換され、それぞれの段階で別々の変換テーブルを使用する
  • 対象のページディレクトリの物理アドレスは、CPUのCR3制御レジスタに保持される
  • 1段階目
    • ページディレクト
      • 対象のページディレクトリから、仮想アドレスの先頭10bitを使用してページテーブルを取得する
  • 2段階目
    • ページテーブル
      • 1段階目で取得したページテーブルから、仮想アドレスの12 ~ 22bitを使用して対応する物理アドレスを取得する

ページディレクトリ / ページテーブル内ののエントリの構造

  • Presentフラグ
    • メインメモリ内に該当するページテーブル・ページが存在するかを表す
    • 1の時、メインメモリ内に存在することを表す
    • 0の時、「ページフォルト例外」が発生する
  • ページフレーム物理アドレスの上位20ビットを持つフィールド
  • アクセス済みフラグ
  • Dirtyフラグ
    • ページテーブルエントリの場合のみ使用される
    • ページフレームに対する書き込みが行われるたびに1が設定される
  • Read / Writeフラグ
    • ページ・ページテーブルのアクセス権を表す
  • User / Supervisorフラグ
    • ページ・ページテーブルにアクセスするのに必要な特権レベルを表す
  • PCDフラグ / PWTフラグ
    • ハードウェアキャッシュが、ページまたはページテーブルを処理する方法を制御する
  • Page Sizeフラグ
    • ページディレクトリエントリの場合のみ使用される
    • エントリが2MBまたは4MBのページフレームを参照する場合は1を設定する (拡張ページングを参照)
  • Globalフラグ
    • ページテーブルエントリの場合のみ使用される

拡張ページング

  • ページのサイズを4KBではなく、4MBにする機能
  • ページテーブルが使われなくなり、物理アドレスへの変換が1段階になる

メモリのセグメント機構について

メモリのセグメント機構について学習したため、そのまとめとしてここに整理する。


セグメントセレクタ

  • セグメントを一意に識別するための16bitのフィールド
  • 各フィールドの役割
    • RPL (0 ~ 1bit目)
    • Requestor Priviledge Level
    • セグメントセレクタをCSに読み込んださいのCPUの特権レベルを指す
    • TI (2bit目)
    • Table Indicator
    • セグメントディスクリプタがGDTにあるか、またはLDTにあるかを示す
    • GDT = 0, LDT = 1
    • インデックス (3 ~ 15bit目)
    • GDTもしくはLDTにある、セグメントディスクリプタのアドレス

セグメントディスクリプタ

  • 8byte長、対応するセグメントの特性を表す
  • GDTもしくはLDTに保存される
  • Linuxでの主なセグメントディスクリプタの用途
  • 各フィールドの役割
    • リミット (0 ~ 15bit)
    • セグメントの終端メモリアドレス = セグメント長
    • ベース (16 ~ 39bit)
    • セグメント先頭のリニアアドレス
    • タイプ (40 ~ 43bit)
    • セグメントの種類とアクセス権
    • S (44bit)
    • システムフラグ。0ならばLDTなどの重要なデータ、1ならば通常のコードセグメント・データセグメントであることを表す
    • DPL (45 ~ 46bit)
    • Descriptor Priviledge Level
    • セグメントへのアクセスを制限するために使用 (該当セグメントにアクセスするために必要な最低限のCPU権限を表す)
    • 1 (47bit)
    • リミット (48 ~ 51bit)
    • AVL (52bit)
    • 0 (53bit)
    • D もしくは B (54bit)
      • 該当セグメントがコード用かデータ用かで呼び方が変わる
    • セグメントオフセットが32ビットの場合は1を設定し、16ビットの場合は0を設定する
    • G (55bit)
      • 粒度(Granularity)を表すフラグ
    • セグメント長をバイト単位で表す場合は0、ページ単位の場合は1
    • ベース (56 ~ 63bit)

GDT / LDT

  • セグメントディスクリプタの一覧を保存するテーブル
  • GDTは通常1つだけ、各プロセスごとにLDTを持つことも可能
  • GDTのアドレスとサイズはCPUのgdtrレジスタに保存される
  • GDT
    • Global Descriptor Table
  • LDT
    • Local Descriptor Table

Linuxにおける主なセグメント

  • ユーザーコードセグメント / ユーザーデータセグメント
  • カーネルコードセグメント / カーネルデータセグメント
    • カーネルモードで動作するコードとデータが配置される
    • __KERNEL_CS__KERNEL_DSマクロでセグメントセレクタを配置

バディシステムについて

バディシステムについて学習したため、そのまとめとしてここに整理する。


バディシステムとは

ページフレーム

  • CPU内に内蔵される「仮想アドレスから物理アドレスに変換する回路」を利用するために、RAMを一定の大きさごとに分割したもの。

メモリ断片化

  • 連続したページフレームの獲得・開放が繰り返し行われると、各ページフレームの隙間に小さな空きページフレームが存在することになってしまうこと。
  • 空きページが十分残っていたとしても、連続したページフレームを確保できない状態になってしまう。

バディシステムの処理 (ページフレーム獲得時)

  • すべてのページフレームを1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024個のブロックに分類し、各ブロックごとに連結リストを作る
  • 獲得要求があった場合、必要のなるページフレームの個数を満たすブロックを空きが見つかるまで順番に探す
    • 例: 256個の連続したページフレームの獲得要求があった場合
    • 256個のブロックから順番に1024個のブロックまで探す
  • 空きが見つかった場合ページフレームを獲得し、残りのページフレームを分割して同じ大きさのブロックの連結リストに繋げる
    • 例: 256個の連続したページフレームを獲得要求に対し、1024個のブロックで空きが見つかった場合
    • 1024個のブロックから256個獲得し、残り768個のブロックを512個と256個に分割し、それぞれ512個と256個の連結リストに繋げる
  • 空きが見つからなかった場合、エラーを返す

バディシステムの処理 (開放時)

  • ページフレーム解放後、条件を満たす2つのブロックがある場合、バディブロックとしてまとめる
  • バディブロックとなる条件
    • 2つのブロックが同じ大きさの場合
    • 2つのブロックが連続している場合
    • 先頭ブロックの物理アドレスが、2 * b * 2 ^ 12の倍数となっている
  • 上記の手順をバディブロックが見つかる限り続ける

Emacs Lisp メモ

Emacs Lispでの開発用メモ

ループ

  • while
    • 継続条件を満たす限り処理を継続
    • 仕様
    • 第1引数: 終了条件

文字列

  • length
    • 文字列の長さを取得
    • 仕様
    • 第1引数: 対象の文字列
    • 戻り値: 対象の文字列の長さ
    • 例: 文字列の長さを受け取って変数に代入
      • (setq len (length "abc"))

入力

  • read-string
    • ユーザーからの入力を待ち受ける
    • 仕様
    • 第1引数: プロンプトとして表示する文字列
    • 戻り値: 入力された値
    • 例: 文字列を受けとって変数に代入
    • (setq user-input (read-string "Input >> "))

フォーマット文字列攻撃

フォーマット文字列攻撃について学習したため、そのまとめここに整理する。

フォーマット文字列攻撃とは

  • printfの引数として与える、フォーマット文字列が外部から指定可能な際に成立する。
    • 入力値をそのまま引数として使用している場合など

主な攻撃内容

  • %xや%pを用いた、メモリ内容の出力
    • printf関数は%xや%pを指定することで、フォーマット文字列が存在するスタックの内容を出力することができる
  • %nを用いた、メモリの書き換え
    • printf関数は%nを指定することで、それまで出力した文字数をメモリに書き込むことができる (フォーマット文字列以降の引数で、書き込むアドレスを指定)
    • %3$nなどのように指定することで、スタックの上から任意の位置を指定して書き込むことも可能
    • %nは4byte単位での書き込みだが、%hn(2byte), %hhn(1byte)も指定可能 (hはharfから?)

Clang / LLVM について

ClangとLLVMについて学習したため、そのまとめとしてここに整理する。


コンパイラのフロントエンドとバックエンドについて

  • コンパイラはフロントエンドとバックエンドに分割し設計されているケースがあり、それぞれ役割がある
    • フロントエンド
    • ソースコードを解析し、中間表現・中間言語と呼ばれるデータに変換する
    • バックエンド
    • フロントエンドによって生成された中間表現から、環境に合わせた機械語バイトコードを生成する
    • その他、最適化なども行う

Clang


LLVM