割り込みと例外
オペレーティングシステムにおける割り込みと例外について学習したため、そのまとめとしてここに整理する。
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段階目
- 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のフィールド
- 各フィールドの役割
セグメントディスクリプタ
- 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)
- オペレーティングシステム用だがLinuxでは使用していない
- 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における主なセグメント
バディシステムについて
バディシステムについて学習したため、そのまとめとしてここに整理する。
バディシステムとは
ページフレーム
- 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から?)