web-dev-qa-db-ja.com

CPUはどの物理アドレスがどの仮想アドレスにマップされているかをどのようにして知るのですか?

私の理解に基づいて、各プロセスは物理アドレスではなく仮想アドレスを介してメモリにアクセスし、これらの仮想アドレスをMMUユニット、および2つまたはそれ以上を介して物理アドレスに変換するのはCPUの責任です。より多くのプロセスが同じ仮想アドレスを持つことができます。

プロセスAが仮想アドレス12345へのアクセスを試み、さらにプロセスBが仮想アドレス12345へのアクセスを試みたとしましょう。

MMU=各プロセスの仮想アドレスを物理アドレスに変換する方法を教えてください。仮想アドレスを物理アドレスにマッピングする各プロセスのマッピングテーブルはありますか(CPUが「プロセス」とは何かを知っていて、その唯一の責任は、どの命令がどのプロセスに属しているかを気にせずに盲目的に命令を実行することであり、「プロセス」はOSの概念にすぎません)?

5
user230989

Linuxでは、カーネルは(CPUの機能に関係なく)3レベルのページテーブルを維持します。トップレベルはページのグローバルディレクトリであり、各プロセスには独自のディレクトリがあります pgd in mm_struct 。したがって、各プロセスは独自のマッピングを持つことができるため、異なるプロセスのアドレス12345は異なる物理アドレスを指します。

CPUはプロセスを実際には認識していませんが、プロセスをサポートする機能を備えている傾向があります。 x86スタイルのCPUには、タスクに関連するさまざまな機能がありますが、実際には無視される傾向があります。プロセススケジューリングはカーネルによって管理されるため、ページテーブルの変更自体を追跡し、タスクを切り替えるときに新しいプロセスのページテーブルに切り替えるために必要なCPU状態を更新できます。 x86 PCでは、ページディレクトリを指す CR 制御レジスタの更新が必要です。

Mel GormanのUnderstanding the Linux Virtual Memory Manager本の Page Table Management の章で概要を説明しています。

1
Stephen Kitt

OSの各プロセスには、PCBと呼ばれるデータ構造があります。 https://en.wikipedia.org/wiki/Process_control_block

PCBには、他のいくつかのものに加えて、オペレーティングシステムで使用されるメモリに応じて、ページテーブル、メモリ制限、セグメントテーブルの情報が含まれています。 PCBはプロセスごとのデータ構造であり、すべてのプロセスに1つあります。

仮想メモリアドレス12345page + offsetに分割されます。たとえば、123はページ番号、45はオフセットです。プロセスごとに、物理メモリ内の同等のページ(フレームと呼ばれる)を見つけるために、そのページテーブルが参照されます。

上記の点を考慮すると、仮想アドレスが同じであっても、物理アドレスは異なります。

各ページの翻訳に関しては、ページテーブルの検索が非常に遅くなる可能性があるため、MMUは、最近翻訳されたページのキャッシュを保持します。TranslationLook Aside Buffer(TLB)と呼ばれます: https: //en.wikipedia.org/wiki/Translation_lookaside_buffer

1
Zul K Irshad

[〜#〜] mmu [〜#〜] は、仮想アドレスを物理アドレスに変換する方法を説明するテーブルにアクセスします。 (物理アドレスを仮想アドレスに変換する必要はありません。同じ物理アドレスに複数の仮想アドレスを介してアクセスしたり、マッピングを解除したりできるため、これは一般的に不可能です。)このテーブルのレイアウトは、CPUアーキテクチャによって異なります。ただし、一般的な原則は常に同じです。テーブルの物理アドレスを含むCPUレジスタがあり、追加のテーブルの物理アドレスを含むCPUレジスタがあります(既存のアーキテクチャでは合計2〜4レベルの場合)。テーブルのレベルまでこれには、データが配置されている物理アドレスが含まれています。各レベルで、使用するテーブルの要素は、仮想アドレスの一部のビットによって決定されます。

MMUは、オペレーティングシステムのプロセス自体を認識していません。 CPUが別のプロセスの実行に切り替えた場合、つまり コンテキストスイッチ が発生した場合、オペレーティングシステムのコンテキスト切り替えコードが、必要に応じてMMUテーブルを更新します。実際には、すべてのUnixシステムは各プロセスのメモリにテーブルのコピーを保持し、MMUレジスタを更新して現在のプロセスの最上位のテーブルを指すようにするだけだと思います。

実際には、オペレーティングシステムプロセスに注意するMMUの一部があります: [〜#〜] tlb [〜#〜] 。 MMUテーブル内のエントリの検索は、複数のメモリアクセスを伴うため、かなりコストがかかります。 TLBはこれらのルックアップのキャッシュです。コンテキストスイッチでは、新しいプロセスのマッピングが異なるため、オペレーティングシステムはTLBを無効にする(つまり、すべてのキャッシュエントリを削除する)必要があります。多くのアーキテクチャでは、OSが各MMUテーブルエントリに「このエントリはプロセスNに属している」というインジケータを配置することができます。 TLBエントリに含まれるプロセス番号が現在のプロセス番号でない場合、TLBエントリはスキップされます。 CPUレジスタには現在のプロセス番号が含まれており、コンテキストスイッチコードがそれを更新します。このメカニズムは、TLBが一度に複数のプロセスに関する情報を含むことができることを意味し、これらのプロセス間で切り替えを行うときのパフォーマンスを向上させます。多くの場合、Nを格納するために使用できるビットは、すべてのOSプロセスIDを格納するために必要なビットよりも少ないため、NはプロセスIDではなく、OSがこの目的のために生成した数値であり、使用された場合、時間とともに変化します。