web-dev-qa-db-ja.com

ZONE_NORMALとそれはカーネル/ユーザーページとの関連付けですか?

Diagram

上記は、512MBの物理メモリしかない場合を示しています。私がこれまで読んだことは、ZONE_NORMALが示されているようにカーネル仮想アドレス空間にマップされているということです。基本的に、512 MBの物理メモリがあり、そのうち496MB相当のZONE_NORMALがカーネル仮想空間にマップされています。この理解に基づいて、以下は私の質問です:

  • ZONE_NORMALはのみカーネルスペースページで構成されていますか?
  • ZONE_NORMALがカーネルページのみで構成され、カーネル空間の仮想アドレス範囲に完全にマップされている場合、ユーザー空間ページはどこに配置されますか?物理メモリにユーザースペースページ用のスペースがないようです。

私が提示したこの場合に示されているように、物理メモリが4GB未満の場合は完全に混乱しています。

誰かがこれに光を当てることができれば本当にありがたいです。

5
TheLoneJoker

32ビットアーキテクチャでは、物理アドレスを参照するための0xffffffff4'294'967'295または4GB)線形アドレス(物理空間ではない)があります。
512 MBの物理ストレージ(実際のRAMスティックがバスに接続されている))でも、カーネルは4'294'967'295(4 GB)線形アドレスを使用して物理的なものを計算します。

Linuxカーネルはこれらの4GB(アドレス)をユーザースペース(ハイメモリ)とカーネルスペース(ローメモリ)に3/1で分割するため、カーネルスペースには1'073'741'823(1 GB)の線形アドレスがあります。使用する。

これらの1GBの線形アドレスは、カーネルからのみアクセス可能であり、さらに分割されています。

ZONE_DMA:16MB未満のメモリのページフレームが含まれます。これは古いISAバスに使用され、RAMの最初の16MBのみをアドレス指定できます。

ZONE_NORMAL:16MB以上および896MB未満のメモリのページフレームが含まれます。これらは、カーネルが直接マップ/アクセスできるアドレスです。

ZONE_HIGHMEM:896 MB以上のメモリのページフレームが含まれます。この境界より上のページフレームは通常、カーネルスペースにマップされないため、カーネルから直接アクセスできません。ユーザースペースのページフレームは、一時的または永続的にここにマッピングできます。

実際の物理的なRAMスペースがさまざまなゾーンによって占有されている量は、実行するプロセスの形式と数によって異なります。

コンソールにfree -mlと入力すると、低メモリと高メモリを含む使用状況を確認できます。

             total       used       free     shared    buffers     cached
Mem:          3022       2116        905          0        105       1342
Low:           839        196        642
High:         2182       1919        263
-/+ buffers/cache:        667       2354
Swap:         2859         93       2766
3
wag

同じ物理ページを複数の仮想アドレスにマップできます。

ZONE_NORMALは、カーネルによってマップできるページで構成されます。そのメモリのほとんどはカーネルに属していませんが、カーネルはある時点ですべてのメモリをマップする必要があります(必ずしもすべて同時にではありません)。たとえば、カーネルがwriteシステムコールを処理している場合、ユーザー提供のバッファーからデータをコピーする必要があります。つまり、バッファーはカーネルの仮想アドレス空間にマップする必要があります。

この図は、メモリが多くない(比較的)単純な状況を示しています。 (ハイエンドのARMデバイスを使用している場合は、今がハイメモリについて学習を開始するときです。)次に、カーネルはすべてのプロセスメモリとすべての物理メモリを同時にマップできます。

カーネルコードで見た仮想メモリの再パーティション化の例を次に示します(正確な数値が可能かどうかはわかりませんが、基本的な考え方は正しいはずです)。つまり、カーネルコードで使用されるポインタの意味を説明しています。

  • 0x00000000..0x00000fff:未割り当て。この範囲のポインタは無効です。
  • 0x00001000..0xbfffffff:プロセスメモリ。これは、検討中のカーネルコードがシステムコールを処理しているプロセスの仮想アドレス空間へのポインタです。その範囲内のページは、割り当てられていないか、割り当てられてスワップインされているか(この場合、物理アドレスもあります)、割り当てられてスワップアウトされている可能性があります(この場合、物理アドレスがありません。 RAMですが、スワップ内に場所があります)。
  • 0xc0000000..0xdfffffff:物理メモリ。この範囲のポインタは、物理アドレスp-0xc0000000を表します。このポインタの解釈は、実際にはMMUに依存しません。
  • 0xe0000000..0xffefffff:未割り当て。この範囲のポインタは無効です。
  • 0xff000000..0xffffffff:カーネルメモリ。これは、カーネルコードまたはデータへのポインタです。この範囲のページには、MMUによって検出された物理アドレスが関連付けられています。

Linuxデバイスドライバー がLinuxカーネルの内部への良い入門書であることがわかりました。最終的には、 source に目を向けることができます。