マエカワの備忘録的な何か

思い立ったが吉日

オペレーティングシステム 其の十 20170628

仮想記憶

メモリには揮発性(RAM)と不揮発性(ROM)がある.
メモリは大きく分けて、コード、データ、ヒープ、スタック領域に分かれている

メモリの抽象化

 アドレス変換について
  CPUから仮想アドレスを取得し、それを変換表で物理アドレスに変換するという方法.
  一枚かませているので「抽象化」.
  これにより、メモリ分離などの問題を解決することができている.

 言葉で書くとこんな感じ
  これまで
   data=mem[address]
  だったのが、
   data=mem[mapping[address]]
  になった感じ.

 また、仮想アドレスすべてに物理アドレスが割り当てられていなくてもいい.割り当てられていないところをマッピング不在と呼ぶ.
 このマッピング表を取り換えることにより、コンテキストスイッチを簡単に実現することができている.

 プロセス間で物理アドレスを共有しないようにすることで、プロセス間のメモリ分離ができる.

変換表のサイズ

 32ビット(=4GB)と推定
 一つのエントリを32ビットとすると、変換表のサイズは4*4=16GBとなり、元の物理アドレスよりも大きくなっている.
  →ページングをする.

ページング

 メモリをページという単位に分割.4KBで区切るのが典型的

 例)物理アドレスが4GB、ページサイズは4KB、ページテーブルのエントリは4Bとする.

  ・物理アドレス空間にあるページは全部で
   4GB/4KB=1MB
  ・物理アドレスすべてをマッピングする場合、ページテーブルのサイズは
   1MB*4=4MB

   になる.ページサイズを大きくしたり小さくしたりするとわかるが、変換表の細かさと、サイズはトレードオフになっている.

ページングとアドレス変換

 ページサイズが4KBということは、下位12ビットは変換後の物理ページの中のアドレスを示していることになる.つまり、上位20ビットのみページテーブルで変換され、物理ページになっているということ.

多段ページテーブル

 上の例で、ページテーブルサイズが4MBのものが出てきたが、この場合、プロセスごとに4MB消費するのはもったいない.
 ということで、ページテーブルの変換につかう上位20ビットを10ビットと10ビットに分割し、多段ページテーブルにしてみる

 例)10ビットと10ビットの多段テーブルを考える.
   ・マップする物理ページが一つだけあるときのエントリ数
    2^10+2^10=2KB(1段目+2段目の一つ)
   ・ページテーブルの最大値
    2^10+2^10*2^10=2^10+2^20=1025KB(1段目+2段目の総数)
   ・最大ページテーブルサイズに到達するために必要な物理ページ数
    2^10=1KB(2段目が一つだけ値あり.後は全部NULL)

   エントリ数を聞かれた場合、1段目の数も数え上げることに注意する.

 メモリアクセスは頻繁に起こるため、多段アドレスでは大変.
  →MMUを使って高速化(ハードの力を頼る)

  TLBを用いる
   →最近変換した結果を覚えているキャッシュ

  流れとしては
   ①TLBを探る
   ②見つからなかったらテーブルページをたどる(page walk
   ③それでもなかったら、ページフォールトでCPUに通知割り込み

アドレス変換の大変さ

 アドレス変換をすると、仮想アドレス空間物理アドレス空間よりも大きくなってしまう.
  →物理アドレス空間が足りなくなってきてしまう.

 →物理メモリに入りきらなかったデータをディスクに避難させる.この書きだすためのディスク上の領域をスワップと呼ぶ.

スワップアウト/イン

 アウトされるとページテーブルの値はマッピング不在になり、データはディスクに預ける
 ページフォールトが出た時はスワップにあるかどうかを調べる.あった場合はスワップインをしてデータを戻し、なかった場合は割り込みハンドラでCPUに通知する.

ページの保護

 ・アクセス属性をつけることが可能
 ・動作モードをつけることが可能

 仮想アドレスを物理アドレスに変換するとき、動作が許可されているかどうかをMMUが調べる.

 スタックオーバーフロー対策にも使われている.
  →実行不可能属性のフラグを付けることで、シェルコードを実行する際MMUが違和感を覚え、処理を停止する.