私はこれらのトピックを学び、多くの記事や本を読みましたが、それらはすべて補足情報が欠けており、私をさらに混乱させました。ここでは、質問をしているときに知っていることを説明します。このトピックが私のような多くの人に役立つことを願っています。また、必要に応じて私の知識の有効性や修正についても学びたいです。
仮想メモリ
一部の記事では、「仮想メモリとは、物理メモリをエミュレートして、実際よりも多くのメモリを確保できるようにするハードディスクの領域のことです。」他のいくつかの記事は、「仮想メモリは、物理メモリとページテーブルのように機能するハードディスクのセクションである物理メモリ(RAM)の組み合わせです。」しかし、それらは異なるものであり、なぜそのように異なる説明があるのか理解できません。
ウィキペディアでも仮想メモリについて説明しているので、2番目の説明に進みましょう。この時点では、物理メモリではなく仮想メモリのアドレスを直接使用しているため、仮想アドレスは理にかなっています。
ちなみに、私のMacでは、8 GBの物理メモリと8 GBの仮想メモリがあると言っています。この場合、VMには物理メモリが含まれますか、それともメモリとして使用されるHDの容量ですか?プログラムで使用できる16GBのメモリはありますか?
質問1:
Intel i5には36ビットのアドレスバスがあり、これは64GBのメモリをアドレスできることを意味します。 4GBをインストールしたとしましょうRAM=コンピュータにインストールしました。ただし、メモリのサイズが異なる多くの異なるシステムで使用されるため、プログラムはインストールされたメモリのサイズを認識しない場合があります。これは仮想メモリが便利になる場所で、インストールされているメモリの実際のサイズを抽象化します。
しかし、プログラムがメモリアドレス0xFFFFFFFFFにアクセスしようとするとどうなりますか?私は4GBしかインストールしておらず、HDにメモリ領域があるかもしれません。
この質問には2つの理論があります。
1。ページテーブルはOSによって維持されるため、OSはそのアドレスをデコードし、どのページであるかを確認し、ページテーブル内のそのページをチェックして、物理アドレスが関連付けられているかどうかを確認します(有効な無効なフラグ)、「はい」の場合、物理アドレス内のページエントリが指す物理アドレス+仮想アドレスで定義されたオフセットに移動し、その値を取得します。そうでない場合、ページフォールトが発生し、OSはセカンダリストレージでそのページを探し、それをフェッチしてメモリに入れ、ページテーブルを更新します。
2。 OutOfMemoryタイプの例外をスローします。これは、指定されたアドレスがアドレス指定できるメモリがないことを示します。
最初の理論の欠点は、プログラムが64GBのメモリを使用しようとするとどうなるかということです。次に、HDには4GBしかないため、60GBのメモリスペースが必要です。ただし、以下のスクリーンショットでは、MACは8GBの仮想メモリしかないことを教えてくれます。
質問2:
プロセスは仮想メモリにどのように配置されますか?つまり、各プロセスには0x0-0xFFFFFFFFFの仮想メモリスペースが利用可能ですか、またはすべてのプロセスが配置される仮想メモリアドレススペースは1つだけですか?
各プロセスで使用可能なすべてのメモリがあると想定している場合、メモリは次のようになります。
仮想メモリの概念が1つしかない場合は、次のようになります。
ページテーブル
したがって、ページテーブルは、物理アドレスと仮想アドレスの間にあるデータ構造です。これは、各ページ(キー)に関連付けられた物理アドレス(値)がある連想配列(または辞書のような)です。
OSは、MMU(メモリ管理ユニット))を使用して、仮想アドレスから物理アドレスへのこの変換を実行します。
質問3:
すべてのプロセスのすべてのページを含む1つの大きな巨大なページテーブルはありますか、または各プロセスには独自のページテーブルがありますか?
ページング
ページングはメモリ管理方法です。仮想メモリと物理メモリは、メモリ管理ユニットによってページ(固定された同じサイズのブロック)に分割されます。この手法は、メモリとセカンダリストレージ間でページを交換して、それらの間でページを交換できるようにする場合に役立ちます。たとえば、プログラムはアドレスにあるデータを要求します。ただし、プログラムが使用しているアドレスは仮想アドレスであり、MMUはページテーブルを使用して変換します。この間、MMUは、要求されたものが存在するかどうかをページテーブルで確認しますページテーブル内にあり、OSがそうでない場合はセカンダリストレージから取得し、ページテーブルを更新します。
質問4:
プロセスが、データをすでに持っている物理アドレスに変換されたアドレスからデータを要求するとします。データがリクエスタープロセスに属しておらず、セカンダリストレージにあるデータに置き換える必要があることはどのようにしてわかりますか?
たとえば、そのページをハードディスクに書き戻すかどうかに使用されるダーティビットがありますが、それがオーナープロセスを決定するものではないと思います。
「仮想メモリ」という用語は、ページファイルが「実際の」メモリ(RAM)ではない割り当てられたメモリの一部を表すため、ページファイルと同義であるように見える人もいます。しかし、ほとんどの人は、「仮想メモリ」を、RAMとページファイルを組み合わせた、オペレーティングシステムがプログラムに提供する抽象化レイヤー全体と見なしています。
お使いのコンピューターにanyページメモリが割り当てられていない可能性は低いと思われますが、これらの定義のどれがMac OSで支持されているかはわかりません。メモリを8 GBの実際のRAMに、合計16 GBの利用可能な(仮想)メモリに。
オペレーティングシステムはメモリの割り当てと割り当て解除の要求を管理するため、必要なことは何でも自由に行えます。私の理解では、ほとんどのオペレーティングシステムはプロセスごとに異なるメモリ割り当てテーブルを持っているため、文字通り同じ仮想メモリアドレスを複数のプログラムに与えることができますが、それらのメモリアドレスはメモリ内の異なる実際のブロックにマップされます。したがって、64ビットオペレーティングシステムは、32ビットアドレスの最大量を複数の32ビットプログラムに割り当てることができます。それらはすべて同じ32ビットメモリアドレスに制限されているわけではありません。
ただし、制限があります。オペレーティングシステムでは、ページファイルが拡大できるサイズに制限を設定できます。したがって、オペレーティングシステムに意図的にそう指示しない限り、64 GBの合計仮想メモリはおそらくないでしょう。そして、たとえそうであっても、64 GBをすべてのプログラムに割り当てることはできないため、OSがプログラムに0xFFFFFFFFF
で仮想アドレスを割り当てる前にOutOfMemory
エラーが発生する可能性があります。 (実際、0xFFFFFFFFF
は実際には0x0
と同様に予約済みのエラーコードの場所であることを知って驚くことはありません。)しかし、プログラムが知っているアドレスはtrueとの相関関係がないのでオペレーティングシステムがメモリ容量の近くを使用していない場合でも、メモリアドレスを使用すると、プログラムが0xFFFFFFFFF
と見なすメモリアドレスが割り当てられる可能性があります。
すべてのプロセスのすべてのページを含む1つの大きな巨大なページテーブルはありますか、または各プロセスには独自のページテーブルがありますか?
おそらく両方...そしていくつか。
したがって、プロセスにアドレス0x00000002
でメモリが割り当てられている場合、そのメモリアドレスから値をロードしようとすると、オペレーティングシステムは、これが実際に実際のメモリアドレス0x00000F23
にマップされていると認識します。これは、実際にCPUレジスタにフェッチされる値を持つメモリアドレスです。または、そのアドレスを含むページをディスク上のどこかに移動したことがわかる場合があります。その場合、オペレーティングシステムはメモリの空の部分を見つけ、ページのデータをディスクからそのメモリに最初にロードします。 (繰り返しになりますが、このメモリアドレスは、プログラムが要求した元のメモリアドレスとは相関関係がありません。)
ページをプルするための空のメモリがない場合、OSはまずメモリからデータをページファイルに移動する必要があります。近い将来使用される可能性が最も低いメモリをインテリジェントに判断しようとします。しかし、プログラムが要求しようとしていた次のメモリを交換するためだけに、ディスクにスワップされた直後にメモリが常に要求される場合があります。ディスクアクセスはメモリアクセスよりも桁違いに遅いため、この "スラッシング"が原因で、メモリが不足しているコンピュータの移動が本当に、本当に遅くなります。
質問にお答えする前に(私がそうだといいのですが)、いくつかの紹介的なコメントがあります。
ここでの問題は、「仮想記憶」には2つの意味があるということです。低レベルのプログラマが使用する技術用語としての「仮想メモリ」は、消費者に説明される「仮想メモリ」とは(ほとんど)何の関係もありません。
技術的な意味では、「仮想メモリ」はメモリ管理システムであり、すべてのプロセスに独自の仮想アドレス空間があり、そのアドレス空間のメモリアドレスは、ハードウェアサポートのあるOSカーネルによって物理メモリアドレスにマップされます(TLBなどの用語を使用します)マルチレベルのページテーブル、ページフォールトとウォークなど)。これは、あなたが興味を持っているVMの意味です(以下で説明します)。
非技術的な意味では、「仮想メモリ」はRAMの代わりに使用されるディスク領域です(スワップ、バッキングストアなどの用語を使用します)。これは特に関心のないVMの感覚ですが、この用語の感覚を主に扱ったり、2つを混同したりする資料を見たことがあるようです。
プログラムがメモリアドレス0xFFFFFFFFFにアクセスしようとするとどうなりますか? 4GBしかない
この場合、「理論1」の方が近くなります。
VMは、プログラムが「認識」して動作するアドレス(仮想アドレス)を物理アドレスから分離します。 4GiBのメモリはphysicalアドレス0x0から0xFFFFFFFF(8 F)にある可能性がありますが、アドレス0xFFFFFFFFF(9 F's)はvirtualアドレス。 0xFFFFFFFFFがプロセスに割り当てられたブロック内にある場合、CPUとカーネル(協調して)はページアドレス0xFFFFFF000(4kページを想定して、下位12ビットをハックオフする)を実際の物理ページに変換します。 (ほぼ)任意の物理ベースアドレス。そのページの物理アドレスが0xeac000(カーネルが仮想ページ0xFFFFFF000を提供したときに確立された関係)であるとすると、仮想アドレス0xFFFFFFFFFのバイトは物理アドレス0x00eacfffにあります。
0xFFFFFFFFFを逆参照すると(4kページを想定)、カーネルはその仮想アドレスにアクセスするようにCPUに「要求」し、CPUは下位12ビットを切り取り、dTLBでページを検索します(変換ルックアサイドバッファーは仮想から物理ページマッピングキャッシュ。少なくとも1つはデータ用で、もう1つは命令用です。ヒットがある場合、CPUは実際の物理アドレスを作成し、値をフェッチします。 TLBミスがある場合、CPUはページフォールトを発生させます。これにより、カーネルはページテーブルを参照(または「ウォーク」)して適切な物理ページを決定し、その値をCPUに「返し」、CPUはそれをキャッシュします。 dTLB(ほとんどすぐに再利用される可能性が高い)。次に、カーネルはCPUにそのアドレスを要求します再度そして今回は、ウォークをトリガーせずに成功します。
私はこの説明がかなり不器用であることを認めます(自分の知識レベルを反映しています)。特に、TLBで特定のプロセスが識別される正確な方法は、100%明確ではなく、少なくともいくらかハードウェア固有です。以前は、すべてのコンテキストスイッチで完全なTLBフラッシュが必要でしたが、最近のIntel CPUには6ビットの「PID」フィールドがあり、フラッシュは時々必要ですが、常にではありませんコンテキストスイッチで必要です。マルチレベルのTLB、PTE(ページテーブルエントリ)を記述し、データと命令のキャッシュでこれの重要性に対処できなかったことから、さらに不自然さが生じます(ただし、最新のハードウェアは、アドレスがTLBルックアップと同時にいくつかのキャッシュレベルで)。
プロセスは仮想メモリにどのように配置されますか?つまり、各プロセスには0x0-0xFFFFFFFFFの仮想メモリスペースが利用可能ですか、またはすべてのプロセスが配置される仮想メモリアドレススペースは1つだけですか?
各プロセスには、独自の完全に異なる仮想メモリ空間があります。これが(ほぼ)VMの全体のポイントです。
昔は、TLBは「プロセス対応」ではありませんでした。すべてのコンテキストスイッチは、TLBが完全にフラッシュされる必要があることを意味しました。現在、TLBエントリには短い「プロセスコンテキスト」(PCID?)フィールドがあり、選択的なフラッシュがサポートされているため、PID(または、PCID:ある種のPIDのハッシュ)と考えることができます。仮想ページアドレスの前に付加されるため、TLBはより多くのプロセスを認識し、PCIDが別のプロセスと衝突した場合に、これらのエントリのみをフラッシュする必要があります(2つのプロセスが同じPCIDにマップされます)。
すべてのプロセスのすべてのページを含む1つの大きな巨大なページテーブルはありますか、または各プロセスには独自のページテーブルがありますか?
これはもちろんOS固有ですが、私の理解ではLinuxには、ページテーブルのマルチレベルセットが1つあり、エントリ(PTE)には個別のPIDではなく、PIDがタグ付けされていますページテーブルを処理します。 I thinkこれの基本的な理由は、多くの仮想から物理へのマッピングが1:1ではなくn:1であるためです。 VMの主な目的を大きく打ち負かす:libc
などのライブラリの指示を含む共有読み取り専用ページ、またはフォーク後に親子間で共有されるコピーオンライトデータページについて考えます。プロセスごとのページテーブルのプロセスごとにこれらのエントリを複製することは、プロセスが作成または終了するときに、プロセス固有のエントリを共通のページテーブルのセットに追加/削除するよりも効率的ではありません。
VMシステムを作成したら、ページフォールトが発生したときにディスクからページを取得する機能を追加し、PTEの「エージング」を実装して、最も最近使用されていないページを配置できるようにするディスク上。これはメモリに制約のあるシステムでは重要な機能ですが、VMシステムが実際にどのように機能するかを理解することとはほとんど関係ありません。