HighmemとLowmemの違いに興味があります。
32ビットアーキテクチャでは、アドレス指定のアドレス空間の範囲RAMは次のとおりです。
0x00000000 - 0xffffffff
または4'294'967'295
(4ギガバイト)。
Linuxカーネルはそれを3/1に分割します(2/2または1/3にすることもできます) 1)ユーザー空間(高メモリ)とカーネル空間(低メモリ)にそれぞれ。
ユーザー空間の範囲:
0x00000000 - 0xbfffffff
新しく生成されたすべてのユーザープロセスは、この領域内のアドレス(範囲)を取得します。ユーザープロセスは一般に信頼されていないため、カーネルスペースへのアクセスは禁止されています。さらに、それらは緊急ではないと見なされ、一般的なルールとして、カーネルはそれらのプロセスへのメモリの割り当てを延期しようとします。
カーネル空間の範囲:
0xc0000000 - 0xffffffff
カーネルプロセスはそのアドレス(範囲)をここで取得します。カーネルはこの1 GBのアドレスに直接アクセスできます(1 GB全体ではなく、128 MBが高メモリアクセス用に予約されています)。
カーネル空間で生成されたプロセスは信頼され、緊急であり、エラーがないと見なされ、メモリリクエストは即座に処理されます。
すべてのカーネルプロセスは、必要に応じてユーザー空間の範囲にもアクセスできます。そしてこれを達成するために、カーネルはユーザー空間(ハイメモリ)からカーネル空間(ローメモリ)にアドレスをマッピングします。上記の128 MBは特にこのために予約されています。
1 分割が3/1、2/2、1/3のいずれであるかは、CONFIG_VMSPLIT_...
オプション;あなたはおそらく/boot/config*
カーネルで選択されているオプションを確認します。
最初に参照するのは Linuxデバイスドライバー (オンラインと本の両方の形式で入手可能)で、特に 15章 にトピックに関するセクションがあります。
理想的な世界では、すべてのシステムコンポーネントが、アクセスする必要のあるすべてのメモリをマップできます。これは、Linuxおよびほとんどのオペレーティングシステムのプロセスに当てはまります。32ビットプロセスは、2 ^ 32バイト弱の仮想メモリにしかアクセスできません(実際のLinux 32ビットアーキテクチャでは実際には約3GB)。カーネルは、システムコールを実行しているプロセスの全メモリ、物理メモリ全体、およびその他のメモリマップされたハードウェアデバイスをマップできる必要があります。
したがって、32ビットカーネルが4GBを超えるメモリをマップする必要がある場合、高メモリサポートでコンパイルする必要があります。ハイメモリは、カーネルのアドレス空間に永続的にマッピングされていないメモリです。 (メモリ不足はその逆です。常にマップされているため、ポインタを逆参照するだけでカーネル内でアクセスできます。)
カーネルコードからハイメモリにアクセスする場合、最初にkmap
を呼び出して、ページデータ構造(struct page
)。 kmap
の呼び出しは、ページのメモリが多い場合でも少ない場合でも機能します。もあります kmap_atomic
これは制約を追加しましたが、より細かいロックを使用するため、マルチプロセッサマシンでより効率的です。 kmap
を介して取得されるポインタはリソースです。アドレス空間を使い果たします。使い終わったら、kunmap
(またはkunmap_atomic
)そのリソースを解放します。すると、ポインタは無効になり、再度kmap
を呼び出すまでページのコンテンツにアクセスできません。
これはLinuxカーネルに関連しています。 Unixカーネルがこれをどのように処理するかはわかりません。
ハイメモリは、ユーザー空間プログラムがアドレス指定できるメモリのセグメントです。メモリ不足には触れられません。
低メモリは、Linuxカーネルが直接アドレス指定できるメモリのセグメントです。カーネルがハイメモリにアクセスする必要がある場合は、まずそれを独自のアドレス空間にマップする必要があります。
最近導入されたパッチにより、セグメントの場所を制御できます。トレードオフは、アドレス可能なメモリをユーザー空間から離して、カーネルが使用前にマップする必要のないより多くのメモリを持つことができることです。
追加のリソース:
HIGHMEMはカーネルのメモリ空間の範囲ですが、アクセスするメモリではありませんが、アクセスしたいものを置く場所です。
典型的な32ビットLinux仮想メモリマップは次のようになります。
0x00000000-0xbfffffff:ユーザープロセス(3GB)
0xc0000000-0xffffffff:カーネルスペース(1GB)
(CPU固有のベクトルなどはすべて無視されます)。
Linuxは1GBのカーネルスペースをLOWMEMとHIGHMEMの2つに分割します。分割はインストールごとに異なります。
インストールでLOWとHIGHのメモリに512MB〜512MBを選択した場合、512MBのLOWMEM(0xc0000000-0xdfffffff)はカーネルのブート時に静的にマッピングされます。通常、このために物理メモリの最初の非常に多くのバイトが使用されるため、この範囲の仮想アドレスと物理アドレスには、たとえば0xc0000000の一定のオフセットがあります。
一方、後者の512MB(HIGHMEM)には静的マッピングがありません(ページを半永久的にそこにマップしたままにすることはできますが、ドライバーコードで明示的に行う必要があります)。代わりに、ページが一時的にここでマップおよびマップ解除されるため、この範囲内の仮想アドレスと物理アドレスには一貫したマッピングがありません。 HIGHMEMの一般的な用途には、シングルタイムデータバッファーが含まれます。
私が覚えている限り、「ハイメモリ」はアプリケーション領域に使用され、「ローメモリ」はカーネルに使用されます。
利点は、(ユーザー空間)アプリケーションがカーネル空間メモリにアクセスできないことです。
メモリ不足はオペレーティングシステム用であると多くの人が言っています。これは通常正しいですが、そうである必要はありません。ハイメモリとローメモリはメモリ空間のほんの2つの部分ですが、Linuxシステムではローメモリはカーネルとユーザープロセスのハイメモリ専用です。
「恐竜の本(オペレーティングシステムの概念)」によると、オペレーティングシステムをローメモリまたはハイメモリに配置できます。この決定に影響を与える主な要因は、割り込みベクトルの場所です。割り込みベクトルはメモリ不足の場合が多いため、プログラマは通常、オペレーティングシステムもメモリ不足に配置します。