Open8

Paging

yukiyuki

入門のところを少し読んだけど、知ってる話が多そうなので最初はさらっといけそう。

yukiyuki

Memory Protection

  • OSのメインの仕事はプログラム同士を独立させることにある。
  • これを実現するためにメモリの領域は別のプロセスが利用できないことを保証させている。
  • ARM Cortex-M は Memory Protection Unit というものを持っている。
  • メモリアクセスごとに、MPU は領域内に存在するアドレスに対するアクセスが正しい権限によるものかどうかを確認し、そうでない場合には例外を投げると言ったことをする。
  • x86 の場合は違ったアプローチを取る: セグメンテーションとページングというメモリ保護機構を持っている。
yukiyuki

Virtual Memory

  • 仮想メモリのアイディアは、裏側にある物理メモリを抽象化すること。
  • ストレージデバイスに直接する前に、翻訳のステップが走ることになる。

仮想メモリ側ではoffsetをもっていて、物理側の開始地点 + offsetによって物理側でどこからどこまで保持するかを決めている。

記事中の仮想メモリでは、プログラムがまったく同じコードを走らせ、仮想メモリ上でも同じ仮想アドレスを使用したとしても、まったく干渉しあわないで処理を進められることが示されている。

yukiyuki

Fragmentation

  • 要するに仮想メモリが好き勝手メモリ領域の確保を行うと、物理上のマッピングで隙間が生まれてしまう。
  • そうすると本来入り切るはずのメモリ領域も入らないことになってしまう。
  • デフラグメンテーションを行って敷き詰め直すことではいるようにする。
  • デフラグには大量のメモリのコピーが必要になることで、パフォーマンスを低下させることがある。
  • フラグメンテーションはそういうわけで、現代の大半のシステムではセグメンテーションが利用されていない原因になっている。
  • 実際、64bit モードの x86 ではセグメンテーションはもはやサポートされていない。
  • ページングと呼ばれる機構が使用されている。これはフラグメンテーションにまつわる問題を解消できる。
yukiyuki

家事が終わったので再開。ページング読むのは概略わかってるし飛ばしてもいいかも…

ページングというのは要するにセグメンテーションなどで発生したデフラグの問題を解消できるように、物理メモリをさらに細かく切っておいて、細かい単位でメモリを管理できるようにしたもの。仮想メモリと物理メモリの間にさらに細かい単位での管理のマッピングとなる page tables を置いておいて、それらによって場所を細かく管理できるようにしたもの。

ページテーブルは多重に置かれることもある。大規模なメモリになったときに、番地が離れているもの同士をひとつのページテーブルで管理しようとすると、上から下まですべてをなめているととても時間がかかるし無駄が多い。そこで、何番地かの塊ごとにページテーブルをわけておき、かつそれに対するインデックスをもったテーブルを用意することで、そうした上から下まですべてをなめる量を減らすことができる。

yukiyuki

x86_64 アーキテクチャの場合は4レベルのページテーブルをもっていて、それぞれのページサイズは 4KiB になっている。

ページテーブルは各々512エントリーをもっていて、各エントリーは8バイトなので、512 * 8 = 4 KiB ということになる。

現在の Intel の Ice Lake という CPU は5レベルのページテーブルを持っていて、微妙に構造が4レベルのものと違うらしい。

yukiyuki

Level 4 テーブル用のアドレスが CR3 レジスタに登録されているので、まずそれを読み込む→次にレベル3ページテーブルを参照する→次にレベル2→次にレベル1を読む→物理アドレスを取得する、みたいな感じでどんどん読み込みが進んでいく。

A pointer to the currently active table is stored in a special CPU register. On x86, this register is called CR3.