Mona/0.3.0/分析/PageManager


Mona/0.3.0/分析

PageManager 現状と改善

いまさらのようにこのクラスを解析してみる。このクラスはメンバ関数が 数多くあり、オーバーロードされているものもたくさんある。

メンバ関数

次のようなメンバ関数がある。

それぞれのメンバ関数の個別の説明

コンストラクタ

  1. 物理ページ数のカウント
  2. 物理ページアロケーションビットマップテーブルの初期化
  3. ページテーブルプールの確保とアロケーションビットマップテーブルの初期化

setup

  1. 0-8MBの物理ページをカーネル用に確保
  2. 0-8MBの物理ページを持つページディレクトリ、テーブルを作成
  3. DMA転送用のメモリプールを確保とアロケーションビットマップテーブルの初期化
  4. VRAM領域をページディレクトリに追加(物理ページの確保はしない)
  5. ページング開始

setPageDirectory, startPaging, stopPaging, flushPageCache

インラインアセンブリ上でCR3レジスタをいじって目的の処理を行う。

allocatePageTable, returnPageTable

allocatePageTable関数は、ページテーブルを確保しているプールから ひとつのページテーブルの領域を確保する。一定数(256個)のページを 確保するとそれ以上ページテーブルを確保できなくなる。 つまり、ページテーブルプールを拡張する仕組みはない。

returnPageTable関数はallocatePageTable関数で確保した ページテーブルを返納する。

ひとつのプロセスは0-8MBのカーネル領域と最大7.3MBのVRAM領域を 消費しているので、起動しただけで4ページは消費されてしまう。

この計算だと64プロセスしか同時起動できない。
追記:実際に確かめてみたところ、31プロセスほどでエラーが出た。計算が 甘かったかもしれない 。(2005-04-04 (月) 21:47:41 追記)

allocateDMAMemory, deallocateDMAMemory

allocateDMAMemory関数はsetup関数により確保してあったメモリプールから DMAのためのメモリを確保する。そして、deallocateDMAMemory関数で 確保していたメモリをメモリプールに返納する。

DMA専用のメモリ領域を確保しなければならない理由は、DMAの仕様で アクセスできるメモリが24ビットアドレスまで出なければならないためである。 (この制限はISAでDMAを利用する場合、つまりフロッピーディスクへのアクセス をする場合で、PCIのDMAを利用するなら制限がなかったような気がする。 いずれにせよ記憶が定かでないし、該当する資料が見当たらないので ここでは明言しないことにする。)

allocatePhysicalPage

オーバーロード関数が次の4通り存在する。

  1. ページは確保せず、属性のみ設定する。というかsetAttribute関数と同じ
  2. ページを確保した上で属性を設定する。
  3. 指定したリニアアドレスの属性を物理ページのアドレスも含めて設定。内部で1.を呼び出す。
  4. 指定したリニアアドレスにページを確保して属性を設定。内部で2.を呼び出す。

returnPhysicalPages

指定したページディレクトリが持つ物理メモリを全て開放する。ただし、 カーネル領域とVRAM領域のメモリは開放しない。

getPhysicalAddress

指定したリニアアドレスを物理アドレスに変換する。変換できればTrueを返す。

setAttribute

オーバーロード関数が次の3通り存在する

  1. ページの属性のみ設定。物理ページのアドレスは指定しない。
  2. ページの属性と物理ページのアドレスを指定する。
  3. ページディレクトリとリニアアドレスから属性と指定するページを指定する。内部で1.を呼び出す。

setAbsent

ページディレクトリ、開始リニアアドレス、大きさを指定しする。開始リニアアドレス から指定された大きさのメモリ領域の属性を「物理ページが確保されていない」状態にする。ただ、開始リニアアドレスが4キロバイトのアライメントに沿っていないと 指定された領域の最後のページの属性が変更できない恐れがある。 このことに関しては私の日記 http://d.hatena.ne.jp/tkralia/20050328/ で説明 しているが、このWikiへの転載の要望があればそうするつもりである。

createKernelPageDirectory

カーネルプロセスINITおよびIDLEプロセスが使用するページディレクトリを 作成する。このページディレクトリでは0-64MBまでのメモリ領域に自由に アクセスできる。また、VRAM領域にアクセスできるようにも設定している。

createNewPageDirectory

ユーザープロセス用のページディレクトリを設定する。このページディレクトリでは 0-8MBの領域をカーネルようの領域とし、システムコール実行時にカーネルがもつ データおよび関数にアクセスできるようにしている。また、VRAM領域の 設定も行う。

createPageDirectoryForV86

仮想x86モードで動作するプロセスのためのページディレクトリを作成する。 このページディレクトリではまず8MBのメモリ領域を確保するが、初めの 1MBはユーザーモードでアクセスできるようになっている。ちなみにVRAM領域の 設定は行っていない。尚、現在のMONAで仮想x86モードで動くアプリケーションは ない。(と思う。)

isPresent

指定されたページが存在するかどうかを調べる。

pageFaultHandler

スレッドを実行中ページフォルトに遭遇するとこの関数が呼び出される。 この関数では次の処理を行っていく。

  1. CR3レジスタが正しい値かどうかをチェック
  2. どのメモリ領域(管理セグメント)でフォールトを起こしたのかを調べて、 処理を丸投げする。
  3. 上で挙げた範囲外のアクセスであれば非許可アクセスである。スタックオーバー フローかどうかを調べて、その旨を表示し、スレッドを停止する。

考察

考え中です。

コメント

最新の1000件を表示しています。 コメントページを参照

お名前:
  • ↓の部分がどのような計算で64プロセスになるか教えていただいてもよろしいでしょうか。 -- ひげぽん 2005-04-02 (土) 22:48:27
    • 確かにプロセスの数が増えても、システム全体として消費するメモリは15.3MB程度ですが、それぞれのプロセスがその15.3MBのメモリを参照するためにページテーブルを消費します。
    • 現在の設計ではページテーブルの数に限り(?)があるのでその制限から 64プロセスまでしか同時起動できないと書いたわけです。
  • お答えします。TAKA 2005-04-03(日) 14:20:00

PageManagerのコンストラクタで1MB + 4096Byte の領域を確保しています。これは 後に使用するページテーブルやページディレクトリのための領域効率的に、 かつ、4KByteのアライメントに沿わせるように確保するためです。

さて、コンストラクタで確保したのは1MB + 4096 Byteで4KByteのアライメントを 考慮すれば256ページの領域になります。つまり、256個のページテーブルが 確保できたわけです。ところで、ひとつのプロセスあたり少なくとも4つのページ テーブルとひとつのページディレクトリが必要になりますから、このままでは 51個のプロセスしか起動できません。(先日書いた64個というのは ページディレクトリを数えるのを忘れていたため。ページディレクトリを含めて 5ページ消費されてしまうので制限がきつくなってしまった。)

ページテーブルのための領域を必要に応じて確保するようにすればいいのですが、 allocatePageTable関数では初めに確保した領域を使い切ってしまうと、つまり、

foundMemory = BitMap::NotFound

になってしまうと、そこで処理が止まってしまいます。つまり、51個 (カーネルプロセスも含む)のプロセスが起動してしまうと、それ以上プロセスを 起動させようとしても出来なくなってしまいます。

  • 明快な解説ありがとうございます。こんな実装にしていたのをすっかり忘れていました。以前はページテーブルの割り当てが非効率だったのでこの実装にしていたのだと思います。この部分を動的に拡張するようにするか、1MBの部分をもっと増やすか迷いますね。 -- ひげぽん 2005-04-03 (日) 20:26:28
  • 実際に確かめてみましたが、半分の31プロセスほど起動したところでエラーになってしまいました。計算が甘かったかもしれません。 -- TAKA 2005-04-04 (月) 21:48:36
  • 日記の分析読みました。31プロセスはすくないですね。 -- ひげぽん 2005-04-04 (月) 23:34:44

1つのプロセスが使用するメモリについて

最新の10件を表示しています。 コメントページを参照

  • ↓の部分がどのような計算で64プロセスになるか教えていただいてもよろしいでしょうか。 -- ひげぽん 2005-04-02 (土) 22:48:27
    • 確かにプロセスの数が増えても、システム全体として消費するメモリは15.3MB程度ですが、それぞれのプロセスがその15.3MBのメモリを参照するためにページテーブルを消費します。
    • 現在の設計ではページテーブルの数に限り(?)があるのでその制限から 64プロセスまでしか同時起動できないと書いたわけです。
  • お答えします。TAKA 2005-04-03(日) 14:20:00

PageManagerのコンストラクタで1MB + 4096Byte の領域を確保しています。これは 後に使用するページテーブルやページディレクトリのための領域効率的に、 かつ、4KByteのアライメントに沿わせるように確保するためです。

さて、コンストラクタで確保したのは1MB + 4096 Byteで4KByteのアライメントを 考慮すれば256ページの領域になります。つまり、256個のページテーブルが 確保できたわけです。ところで、ひとつのプロセスあたり少なくとも4つのページ テーブルとひとつのページディレクトリが必要になりますから、このままでは 51個のプロセスしか起動できません。(先日書いた64個というのは ページディレクトリを数えるのを忘れていたため。ページディレクトリを含めて 5ページ消費されてしまうので制限がきつくなってしまった。)

ページテーブルのための領域を必要に応じて確保するようにすればいいのですが、 allocatePageTable関数では初めに確保した領域を使い切ってしまうと、つまり、

foundMemory = BitMap::NotFound

になってしまうと、そこで処理が止まってしまいます。つまり、51個 (カーネルプロセスも含む)のプロセスが起動してしまうと、それ以上プロセスを 起動させようとしても出来なくなってしまいます。

  • 明快な解説ありがとうございます。こんな実装にしていたのをすっかり忘れていました。以前はページテーブルの割り当てが非効率だったのでこの実装にしていたのだと思います。この部分を動的に拡張するようにするか、1MBの部分をもっと増やすか迷いますね。 -- ひげぽん 2005-04-03 (日) 20:26:28
  • 実際に確かめてみましたが、半分の31プロセスほど起動したところでエラーになってしまいました。計算が甘かったかもしれません。 -- TAKA 2005-04-04 (月) 21:48:36
  • 日記の分析読みました。31プロセスはすくないですね。 -- ひげぽん 2005-04-04 (月) 23:34:44
お名前:

MENU

now: 4

リンク


最新の20件
2018-05-03 2017-09-29 2017-04-25 2017-01-10 2016-12-11 2016-10-04 2016-08-14 2016-06-05 2016-05-29 2016-04-15 2015-12-28 2013-02-25 2013-02-21 2013-02-20 2013-02-12 2013-02-11 2013-02-10
最新の20件
2010-02-01 2010-01-31 2010-01-30 2010-01-29 2010-01-16

Counter: 4031, today: 2, yesterday: 1

リロード   新規 編集 凍結 差分 添付 複製 改名   トップ 一覧 検索 最終更新 バックアップ   ヘルプ   最終更新のRSS

Last-modified: 2008-03-28 (金) 15:47:55 (3762d);  Modified by mona
PukiWiki 1.4.6 Copyright © 2001-2005 PukiWiki Developers Team. License is GPL.
Based on "PukiWiki" 1.3 by yu-ji
Powered by PHP 5.2.17
HTML convert time to 0.063 sec.