上記は、512MBの物理メモリしかない場合を示しています。私がこれまで読んだことは、ZONE_NORMALが示されているようにカーネル仮想アドレス空間にマップされているということです。基本的に、512 MBの物理メモリがあり、そのうち496MB相当のZONE_NORMALがカーネル仮想空間にマップされています。この理解に基づいて、以下は私の質問です:
私が提示したこの場合に示されているように、物理メモリが4GB未満の場合は完全に混乱しています。
誰かがこれに光を当てることができれば本当にありがたいです。
32ビットアーキテクチャでは、物理アドレスを参照するための0xffffffff
(4'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
同じ物理ページを複数の仮想アドレスにマップできます。
ZONE_NORMALは、カーネルによってマップできるページで構成されます。そのメモリのほとんどはカーネルに属していませんが、カーネルはある時点ですべてのメモリをマップする必要があります(必ずしもすべて同時にではありません)。たとえば、カーネルがwrite
システムコールを処理している場合、ユーザー提供のバッファーからデータをコピーする必要があります。つまり、バッファーはカーネルの仮想アドレス空間にマップする必要があります。
この図は、メモリが多くない(比較的)単純な状況を示しています。 (ハイエンドのARMデバイスを使用している場合は、今がハイメモリについて学習を開始するときです。)次に、カーネルはすべてのプロセスメモリとすべての物理メモリを同時にマップできます。
カーネルコードで見た仮想メモリの再パーティション化の例を次に示します(正確な数値が可能かどうかはわかりませんが、基本的な考え方は正しいはずです)。つまり、カーネルコードで使用されるポインタの意味を説明しています。
0x00000000..0x00000fff
:未割り当て。この範囲のポインタは無効です。0x00001000..0xbfffffff
:プロセスメモリ。これは、検討中のカーネルコードがシステムコールを処理しているプロセスの仮想アドレス空間へのポインタです。その範囲内のページは、割り当てられていないか、割り当てられてスワップインされているか(この場合、物理アドレスもあります)、割り当てられてスワップアウトされている可能性があります(この場合、物理アドレスがありません。 RAMですが、スワップ内に場所があります)。0xc0000000..0xdfffffff
:物理メモリ。この範囲のポインタは、物理アドレスp-0xc0000000を表します。このポインタの解釈は、実際にはMMUに依存しません。0xe0000000..0xffefffff
:未割り当て。この範囲のポインタは無効です。0xff000000..0xffffffff
:カーネルメモリ。これは、カーネルコードまたはデータへのポインタです。この範囲のページには、MMUによって検出された物理アドレスが関連付けられています。Linuxデバイスドライバー がLinuxカーネルの内部への良い入門書であることがわかりました。最終的には、 source に目を向けることができます。