まず、32ビットシステムには、RAM上の物理的な場所にアクセスするための0xffffffff
(4'294'967'295
)線形アドレスがあります。
カーネルは、これらのアドレスをユーザー空間とカーネル空間に分割します。
ユーザーは(必要に応じてカーネルも)ユーザー空間(ハイメモリ)にアクセスできます。
16進表記と10進表記のアドレス範囲:
0x00000000 - 0xbfffffff
0 - 3'221'225'471
カーネルスペース(メモリ不足)は、カーネルのみがアクセスできます。
16進表記と10進表記のアドレス範囲:
0xc0000000 - 0xffffffff
3'221'225'472 - 4'294'967'295
このような:
0x00000000 0xc0000000 0xffffffff
| | |
+------------------------+----------+
| User | Kernel |
| space | space |
+------------------------+----------+
したがって、見たメモリレイアウトdmesg
は、カーネル空間での線形アドレスのマッピングに対応しています。
最初に、カーネル自身のページテーブルの初期化を提供する.text、.data、および.initシーケンス(線形から物理アドレスへの変換)。
.text : 0xc0400000 - 0xc071ae6a (3179 kB)
カーネルコードが存在する範囲。
.data : 0xc071ae6a - 0xc08feb78 (1935 kB)
カーネルデータセグメントが存在する範囲。
.init : 0xc0906000 - 0xc0973000 ( 436 kB)
カーネルの初期ページテーブルが存在する範囲。
(および一部の動的データ構造の場合はさらに128 kB。)
この最小アドレス空間は、カーネルをRAMにインストールし、コアデータ構造を初期化するのに十分な大きさです。
使用されているサイズは、括弧内に示されています。たとえば、カーネルコードを見てみましょう。
0xc071ae6a - 0xc0400000 = 31AE6A
10進表記では、それは3'255'914
(3179 kB)です。
第二に、初期化後のカーネル空間の使用
lowmem : 0xc0000000 - 0xf77fe000 ( 887 MB)
カーネルは、lowmem範囲を使用して物理アドレスに直接アクセスできます。
これは完全な1 GBではありません。なぜなら、カーネルは、連続したメモリ割り当てと修正マップされた線形アドレスを実装するために、少なくとも128 MBの線形アドレスを常に必要とするからです。
vmalloc : 0xf7ffe000 - 0xff7fe000 ( 120 MB)
仮想メモリの割り当ては、不連続スキームに基づいてページフレームを割り当てることができます。このスキーマの主な利点は、外部の断片化を回避することです。これは、スワップ領域、カーネルモジュール、または一部のI / Oデバイスへのバッファの割り当てに使用されます。
pkmap : 0xff800000 - 0xffa00000 (2048 kB)
永続的なカーネルマッピングにより、カーネルは、高メモリページフレームのカーネルアドレス空間への長期にわたるマッピングを確立できます。kmap()を使用してHIGHMEMページをマップすると、ここから仮想アドレスが割り当てられます。
fixmap : 0xffc57000 - 0xfffff000 (3744 kB)
これらは、lowmemアドレスのような最後の1 GBだけでなく、RAM内の任意の物理アドレスを参照できる修正マップ線形アドレスです。修正マップされた線形アドレスは、lowmemやpkmapの同僚よりも少し効率的です。固定マッピングに割り当てられた専用のページテーブル記述子があり、kmap_atomicを使用したHIGHMEMページのマッピングはここから割り当てられます。
ウサギの穴をもっと深く掘り下げたい場合:
Linuxカーネルについて