Closed coder2828 closed 1 year ago
@coder2828 良い着眼点かなと思います。
kernel_main_stackのアドレスは、コンパイラによって適当なアドレスに確保されると理解しました。
この認識は正しいです。ですが、kernel_main_stack の領域はアプリケーションに対しては割り当てませんので、特に問題はないかと思います。
アプリケーションに割り当てるためのメモリ領域は BitmapMemoryManager にてページ単位で確保しています。4KiB の境界に揃ったメモリ領域がアプリケーションへ割り当てられることになります。
アプリケーションが使用するメモリ領域は物理アドレス空間ではなく仮想アドレス空間となります。仮想アドレスはページング機構によってアドレス変換が行われ、最終的に物理メモリにアクセスされることになります。そのため、物理メモリ領域で連続しているかどうかはアクセス効率にほとんど影響しないと思います。
@uchan-nos お忙しいところご教示いただきありがとうございます。 物理メモリ上で連続していようがいまいが、MMUが介在するのでアクセス効率は変わらないということですね。
重ねての質問で恐縮なのですが、CPUのキャッシュメモリとの関係性はどうなるのでしょうか。 ちょっと知識が古いかもしれませんが、キャッシュメモリへの読み込みは、CPUが使用したアドレスの近くのデータが近々アクセスされる可能性が高いため、一緒にキャッシュメモリへ読み込まれると学びました。このアドレスが近いデータというのは仮想アドレス空間で扱われるのでしょうか。
よろしくお願いいたします。
私は CPU のキャッシュメモリの仕組みについてはさほど詳しくないので、調べながら回答を書きます。
CPUキャッシュがGoのコードに与える影響(翻訳)|TechRacho by BPS株式会社 によれば、この記事に登場する CPU の場合は L1 キャッシュの cache line は 64 バイトだそうです。 1 回メモリアクセスがあると、その周囲を含めて 64 バイト分が一気にキャッシュに載るということですね。
最近の CPU のキャッシュが物理アドレスで動くのか、仮想アドレスで動くのかはよく知らないのですが、いずれにせよプログラムの動作速度には関係ないと思います。 なぜなら cache line はページ境界をまたがないからです。最も基本的なページのサイズは 4KiB で、これはもちろん cache line の 64 バイト境界とも整合します。 「アドレスが近いデータ」といっても高々 64 バイト先までの範囲の話で、「次のページにあるデータを先読みする」ということはないわけです。
お世話になっております。ご回答いただきありがとうございます。
結局のところ、ページサイズ4KiBを超えては、キャッシュにも読み込まれないので、大きなメモリを獲得するときに物理アドレス上連続になっているかどうかはアクセス性能には影響を与えないということですね。
大みそかにわざわざ時間を取っていただきまして、ありがとうございます。大変参考になりました。
お世話になります。
2.4 のUEFIが確保するメモリマップを見ると、ある程度切りのよいアドレスでマッピングされているかと思います。 対して「8.4 スタック領域の移動」では、rspをkernel_main_stack + 1024 * 1024へコピーされていますが、kernel_main_stackのアドレスは、コンパイラによって適当なアドレスに確保されると理解しました。
後ほど出てくるかと思いますが、アプリケーションに対して割り当てるメモリ領域は連続した物理アドレスを割り当てたほうが、アクセス効率がよくなるのではと思いました。上記のスタック領域を適当なアドレスで確保してしまうと、アプリケーションに対して大きなメモリを連続領域で与えられなくなってしまうのではないかと考えました。(コンパイラがうまくやってくれるのかもしれませんが。)
そこで、適用するシステムに応じて、OS開発者が物理メモリをうまく分割したメモリマップを作成し、kernel_main_stackもコンパイラ任せではなく、適切な場所に確保したほうが良いのではないかと考えました。 一般的にそのようなことはしないのでしょうか。 またしたい場合は、MemoryDescripterを見て、使用できる領域をスタック領域として設定したらよいかと思いますが、あっているでしょうか。
ご教示のほどよろしくお願いいたします。