web-dev-qa-db-ja.com

Linuxカーネルは1GB未満の物理メモリをどのように管理しますか?

私はLinuxカーネルの内部を学んでおり、「Linuxカーネルについて」を読んでいるときに、かなりの数のメモリ関連の質問が私を襲いました。そのうちの1つは、たとえば512 MBの物理メモリがシステムにインストールされている場合に、Linuxカーネルがメモリマッピングを処理する方法です。

私が読んだように、カーネルは(または16)MB-896MB物理RAMを0xC0000000線形アドレスにマップし、直接アドレス指定できます。したがって、上記の場合、私は512MBしか持っていません:

  • カーネルはどのようにしてわずか512MBから896MBをマップできますか?説明されているスキームでは、カーネルは、すべてのプロセスのページテーブルが0xC0000000から0xFFFFFFFF(1GB)の仮想アドレスを0x00000000から0x3FFFFFFF(1GB)の物理アドレスに直接マップするように設定します。しかし、512 MBの物理RAMしかない場合、仮想アドレスを0xC0000000-0xFFFFFFFFから物理0x00000000-0x3FFFFFFFにマップするにはどうすればよいですか?ポイントは、物理的な範囲が0x00000000〜0x20000000しかないことです。

  • この状況でのユーザーモードプロセスはどうですか?

  • すべての記事では、4 GBのメモリをインストールし、カーネルが1 GBをカーネル空間にマップし、ユーザープロセスが残りのRAMを使用する場合の状況についてのみ説明しています。

理解を深めるのに助けていただければ幸いです。

ありがとう..!

48
TheLoneJoker

すべての仮想(線形)アドレスを何かにマップする必要があるわけではありません。コードがマップされていないページにアクセスすると、ページフォールトが発生します。

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

4 GBの仮想メモリには、2つのセクションがあります。0x0... 0xbfffffff-プロセス仮想メモリであり、0xc0000000 ..0xffffffffはカーネル仮想メモリです。

  • カーネルはどのようにしてわずか512MBから896MBをマップできますか?

最大896MBまでマップします。したがって、512しかない場合は、512MBしかマップされません。

物理メモリが0x00000000から0x20000000にある場合、仮想アドレス0xC0000000から0xE0000000への直接カーネルアクセス用にマップされます(線形マッピング)。

  • この状況でのユーザーモードプロセスはどうですか?

ユーザープロセスの物理メモリは、仮想アドレス0x0 .... 0xc0000000にマッピングされます(順次ではなく、ランダムなページ間マッピング)。このマッピングは、0..896MBからのページの2番目のマッピングになります。ページは無料のページリストから取得されます。

  • Phys RAMのユーザーモードプロセスはどこにありますか?

どこでも。

  • すべての記事では、状況のみを説明しています4GBのメモリをインストールそして

いいえ。すべての記事で、4Gbの仮想アドレス空間がどのようにマッピングされるかが説明されています。仮想メモリのサイズは常に4GBです(x86のPAE/PSEなどのメモリ拡張機能のない32ビットマシンの場合)

RobertLoveの本8.1.3. Memory ZonesLinux Kernel Development(私は第3版を使用)で述べられているように、物理メモリにはいくつかのゾーンがあります。

  • ZONE_DMA-16MB未満のメモリのページフレームが含まれています
  • ZONE_NORMAL-16MB以上および896MB未満のメモリのページフレームが含まれます
  • ZONE_HIGHMEM-896MB以上のメモリのページフレームが含まれています

したがって、512 MBの場合、ZONE_HIGHMEMは空になり、ZONE_NORMALには496MBの物理メモリがマップされます。

また、本の2.5.5.2. Final kernel Page Table when RAM size is less than 896 MBセクションもご覧ください。 896MBよりメモリが少ない場合です。

また、ARM仮想メモリレイアウトの説明があります: http://www.mjmwired.net/kernel/Documentation/arm/memory.txt

行63PAGE_OFFSET high_memory-1は、メモリの直接マップされた部分です。

44
osgx

ハードウェアは メモリ管理ユニット を提供します。これは、メモリアクセスを傍受して変更できる回路の一部です。プロセッサがRAMにアクセスするときはいつでも、例えば実行する次の命令を読み取るため、または命令によってトリガーされるデータアクセスとして、あるアドレスで読み取ります。これは大まかに言えば32です。 -ビット値。 32ビットワードは40億を少し超える個別の値を持つことができるため、4 GBのアドレス空間があります。これはバイト数です。一意のアドレスを持つことができます。

したがって、プロセッサは、「アドレスxでバイトをフェッチし、それを私に返す」として、要求をメモリサブシステムに送信します。リクエストはMMUを通過し、MMUがリクエストの処理方法を決定します。 MMUは、4 GBのスペースを実質的にページに分割します;ページサイズは使用するハードウェアによって異なりますが、通常のサイズですMMUは、各ページのアクセスをどのように処理するかを示すテーブルを使用します。アクセスは、書き換えられたアドレスで許可されます(ページエントリには次のように記載されています:「はい、アドレスxを含むページが存在し、物理的にRAMアドレスyにあります ")または拒否された場合、カーネルが呼び出されてさらに処理が行われます。カーネルは、問題のあるプロセスを強制終了するか、何らかの作業を行ってMMUテーブルを使用して、アクセスを再試行できるようにします。今回は正常に実行されます。

これが仮想メモリの基礎です。観点からは、プロセスにはRAMがいくらかありますが、カーネルはそれをハードディスクに移動しました。 「スワップスペース」。対応するテーブルは、MMUテーブルで「不在」としてマークされます。プロセスがデータにアクセスすると、MMUはカーネルを呼び出し、カーネルはからデータをフェッチします。スワップは、物理RAMの空き領域に戻し、MMUテーブルを変更して、その領域を指すようにします。カーネルは、トリガーされた命令で、プロセスコードにジャンプして戻ります。プロセスコードは、メモリアクセスにかなりの時間がかかったことを除いて、ビジネス全体を何も認識していません。

MMUはアクセス権も処理します。これにより、プロセスが他のプロセスやカーネルに属するデータを読み書きできなくなります。各プロセスには独自のMMUテーブル、およびカーネルはそれらのテーブルを管理します。したがって、各プロセスは、プロセスが4 GBのRAM-を除いて、マシン上に単独で存在するかのように、独自のアドレススペースを持ちます。対応するページが不在または禁止としてマークされているため、カーネルから正しく割り当てられなかったメモリにアクセスしない方がよいでしょう。

カーネルが何らかのプロセスからのシステムコールを介して呼び出される場合、カーネルコードはプロセスのアドレス空間内で実行される必要があります。したがって、カーネルコードは各プロセスのアドレス空間のどこかにある必要があります(ただし、保護されています:MMUテーブルは非特権ユーザーコードからカーネルメモリへのアクセスを防ぎます)。コードにはハードコードされたアドレスを含めることができるため、カーネルは、すべてのプロセスで同じアドレスにある方がよいでしょう。従来、Linuxでは、そのアドレスは0xC0000000です。MMU =各プロセスのテーブルは、アドレス空間のその部分をphysicalRAMカーネルが実際にロードされたブロック)にマップしますカーネルメモリがスワップアウトされることは決してないことに注意してください(スワップスペースからデータを読み戻すことができるコード自体がスワップアウトされた場合、事態は非常に速く悪化します)。

PCでは、32ビットモードと64ビットモード、セグメントレジスタ、およびPAE(一種の第2レベルMMU)として機能するため、状況は少し複雑になる可能性があります。基本的な概念は同じです。各プロセスは仮想4GBアドレス空間の独自のビューを取得し、カーネルはMMUを使用して、各仮想ページを適切な物理にマップします。 RAM内の位置、またはまったくどこにもありません。

17
Thomas Pornin

osgxには優れた答えがありますが、誰かがまだ理解していないコメントがあります。

すべての記事では、4 GBのメモリをインストールし、カーネルが1 GBをカーネル空間にマップし、ユーザープロセスが残りのRAMを使用する場合の状況についてのみ説明しています。

ここに多くの混乱があります。 仮想メモリがあり、物理メモリがあります。すべての32ビットCPUには4GBの仮想メモリがあります。 Linuxカーネルの従来の分割はユーザーメモリとカーネルメモリ用に3G/1Gでしたが、新しいオプションでは異なるパーティション分割が可能です。

なぜカーネルとユーザースペースを区別するのですか? -私自身の質問

タスクがスワップするときは、MMUを更新する必要があります。カーネルMMUスペースは、すべてのプロセスで同じままである必要があります。カーネルは、で割り込みと障害要求を処理する必要があります。どんなときも。

仮想から物理へのマッピングはどのように機能しますか? -私自身の質問です。

仮想メモリには多くの順列があります。

  • 物理的なRAMページへの単一のプライベートマッピング。
  • 単一の物理ページへの重複した仮想マッピング。
  • [〜#〜] sigbus [〜#〜]またはその他のエラーをスローするマッピング。
  • ディスク/スワップに裏打ちされたマッピング。

上記のリストから、物理メモリよりも多くの仮想アドレス空間がある理由を簡単に理解できます。実際、フォールトハンドラーは通常、プロセスメモリ情報を検査して、ページがマップされている(つまり、プロセス)、ただしメモリ内ではありません。この場合、フォールトハンドラーはI/Oサブシステムを呼び出してページを読み取ります。ページが読み取られ、仮想アドレスが新しい物理アドレスを指すようにMMUテーブルが更新されると、障害の原因となったプロセスが再開されます。

上記を理解すると、物理メモリよりも大きな仮想マッピングが必要な理由が明らかになります。これは、メモリスワッピングがサポートされる方法です。

他の用途があります。たとえば、2つのプロセスが同じコードライブラリを使用する場合があります。リンクが原因で、プロセス空間でそれらが異なる仮想アドレスにある可能性があります。この場合、物理メモリを節約するために、異なる仮想アドレスを同じ物理ページにマップできます。これは、新しい割り当てでは非常に一般的です。それらはすべて、物理的な「ゼロページ」を指しています。メモリをタッチ/ライトすると、ゼロページがコピーされ、新しい物理ページが割り当てられます(COWまたはコピーオンライト)。

また、仮想ページを1つをcachedとして、もう1つをnon-cachedとしてエイリアス化すると便利な場合もあります。 2つのページを調べて、キャッシュされているデータとキャッシュされていないデータを確認できます。

主に仮想物理は同じではありません!簡単に説明できますが、LinuxVMMコードを見ると混乱することがよくあります。

4
artless noise

-

こんにちは、実際、私はx86ハードウェアプラットフォームで作業していないので、私の投稿にいくつかの技術的なエラーが存在する可能性があります。

私の知る限り、0(または16)MB〜896MBの範囲が特別にリストされていますが、その数よりもRAMが多い場合、たとえば、ボードに1GBの物理的なRAMがあります。これは「低メモリ」と呼ばれます。ボード上に896MBよりも多くの物理RAMがある場合、残りの物理RAMはhighmemと呼ばれます。

あなたの質問について言えば、ボードには512MiBytesの物理的なRAMがあるので、実際には896もhighmemもありません。

カーネルが表示およびマップできる合計RAMは512MBです。

'物理メモリとカーネル仮想アドレスの間に1対1のマッピングがあるため、カーネル用に512MiBytesの仮想アドレス空間があります。前の文が正しいかどうかは本当にわかりませんが、それが私の頭の中にあります。

つまり、512Mバイトがある場合、カーネルが管理できる物理的なRAMの量も512Miバイトであり、さらに、カーネルは512Mバイトを超えるような大きなアドレス空間を作成できません。

ユーザースペースを参照してください。1つの異なるポイントがあります。ユーザーのアプリケーションのページをハードディスクにスワップアウトできますが、カーネルのページはスワップアウトできません。

したがって、ユーザースペースについては、ページテーブルやその他の関連モジュールの助けを借りて、まだ4Gバイトのアドレススペースがあるようです。もちろん、これは仮想アドレス空間であり、物理的なRAM空間ではありません。

これが私が理解していることです。

ありがとう。

3
shawn xy bai

物理メモリが896MB未満の場合、Linuxカーネルはその物理アドレスに直線的にマッピングされます。

詳細については、こちらをご覧ください。 http://learnlinuxconcepts.blogspot.in/2014/02/linux-addressing.html

0
JIN007