Linux のメモリ管理とアドレス指定の詳細な紹介

Linux のメモリ管理とアドレス指定の詳細な紹介

1. コンセプト

メモリ管理モード

セグメント型: メモリは複数のセグメントに分割され、各セグメントは連続したメモリであり、異なるセグメントは異なる用途に対応します。各セグメントのサイズが均一ではないため、メモリの断片化やメモリスワップの非効率などの問題が発生します。

ページ化: メモリは管理のために複数のメモリ ページに分割されます。たとえば、Linux システムでは、各ページのサイズは4KBです。ページングにより、小さなメモリ断片は発生しません。しかし、メモリの断片化の問題は依然として残っています。

段落ページ形式: 段落形式とページ形式の組み合わせ。

住所種別分類

論理アドレス: プログラムが使用するアドレス、通常はセグメントメモリ管理によってマップされていないアドレスを論理アドレスと呼びます。

リニアアドレス: セグメント化されたメモリ管理によってマップされるアドレスは、リニアアドレス、または仮想アドレスと呼ばれます。

仮想アドレス: セグメント化されたメモリ管理によってマップされたアドレスは、線形アドレス、または仮想アドレスと呼ばれます。

物理アドレス: 物理メモリアドレス

例:

Inetel プロセッサでは、論理アドレスは「セグメント メモリ管理」変換前のアドレスであり、リニア アドレスは「ページ メモリ管理」変換前のアドレスです。

セグメント化されたメモリ管理によってマップされるアドレスはもはや「物理アドレス」ではなく、Intel では「リニア アドレス」(仮想アドレスとも呼ばれる) と呼ばれています。したがって、セグメント化メモリ管理では、まず論理アドレスをリニア アドレスにマッピングし、次にページ化メモリ管理ではリニア アドレスを物理アドレスにマッピングします。

Linux のメモリは主にページ メモリによって管理されますが、セグメント メカニズムも使用されます。 Linux カーネルが現在採用しているアプローチは、セグメント マッピング プロセスを事実上無効にすることです。

Intel の最も初期のプロセッサである 80286 は完全にセグメントベースでしたが、80386 にはセグメントとページの両方の管理機能がありました。

2. ページ管理

x86 アーキテクチャ 32 ビット CPU

セカンダリ ページ テーブル アドレス指定方法では、メモリ ページのサイズは 4 KB、第 1 レベルのページ ディレクトリ テーブルには 1024 個のエントリがあり、第 2 レベルのページ テーブルには 1024 個のエントリがあり、ページ テーブル エントリは 4 バイトです。第 1 レベルのページ ディレクトリ テーブル エントリがすべて割り当てられ、必要に応じて第 2 レベルのページ テーブルが作成されます。 (局所性原理)。

仮想アドレス 32 ビット

10+10+12 は、それぞれレベル 1 ページ テーブル番号、レベル 2 ページ テーブル エントリをインデックスし、物理ベース アドレスのオフセット アドレスを記録します。 PAE メカニズムを使用した後、32 ビット システムでサポートされる最大メモリは 64 GB (アドレスは 32+4=36 ビット) になります。

線形アドレス指定物理アドレスステップ

まず、10 ビットのアドレス指定レベル 1 ページ テーブル番号を使用します。レベル 1 ページ テーブル番号には、レベル 2 ページ テーブルのアドレスが記録されます。

レベル 2 ページ テーブルのアドレスを見つけた後、仮想アドレスの残りの 10 ビットに基づいて、レベル 2 ページ テーブル内のエントリの場所が見つかります。

レベル 2 ページ テーブルのエントリが見つかると、エントリには物理アドレスにマッピングされる仮想アドレスの開始アドレスが記録されます。エントリのサイズは 4 バイト (32 ビット) です。

最終的な物理アドレスは、見つかった物理アドレスの開始アドレスと、仮想アドレスの最後の12ビットをオフセットとして組み合わせて計算されます。

x86 アーキテクチャ 64 ビット CPU

ページテーブルにはさらにレベルがある

グローバル ページ ディレクトリ PGD (ページ グローバル ディレクトリ) 上位ページ ディレクトリ PUD (ページ上位ディレクトリ) 中間ページ ディレクトリ PMD (ページ中間ディレクトリ) ページ テーブル エントリ PTE (ページ テーブル エントリ)

線形アドレス指定物理アドレスステップ

リニアアドレスは48ビット、最大物理アドレスは52ビット、実際の物理メモリアドレスバス幅は40ビットで、1TBの物理メモリをサポートします。x86_64には4レベルのページテーブルがあり、原理はx86システムと同じで、レイヤーごとにアドレス指定されます。CR3レジスタには最上位テーブルの開始物理アドレスが格納されているため、アドレス指定の最初のステップはCR3レジスタの値を取得することです。各PTEエントリのサイズは8バイト、つまり64ビットです。

TLB

CPU チップには、プログラムによって最も頻繁にアクセスされるページ テーブル エントリを格納するためのキャッシュが追加されています。このキャッシュは TL (Translation Lookaside Buffer) です。通常、ページ テーブル キャッシュ、リダイレクト バイパス キャッシュ、高速テーブルなどと呼ばれます。次に、CPU のメモリ管理ユニット MMU がアドレスを検索すると、最初に TLB をチェックします。見つからない場合は、通常のページ テーブルのチェックを続けます。

固有名詞

PDT: ページ ディレクトリ テーブル、マルチレベル ページ テーブル、第 1 レベル ページ テーブル、32 ビット システムには 1024 個のページ ディレクトリがあります
PTT: ページ テーブル エントリ、マルチレベル ページ テーブル、セカンダリ ページ テーブル、32 ビット システムでは各ページ ディレクトリの下に 1024 のページ テーブル エントリがあり、各エントリは 4 バイトです。
PDE: ページテーブルのベースアドレス。PDT内の項目です。
PTE: ページのベースアドレス、PTTの1つ
GDT: グローバル記述子テーブル。論理アドレスを線形アドレスに変換するために使用されます。
LDT: ローカル記述子テーブル。論理アドレスを線形アドレスに変換するために使用されます。

3. 住所区分

32 システムカーネル 1G: 0xC0 00 00 01 - 0xFF FF FF FF
ユーザー 3G: 0x00 00 00 00 - 0xC0 00 00 00
0xC0 00 00 00 == 3G

64 ビット システム:
カーネル 128T: 0xFF FF 80 00 00 00 00 00 - 0xFF FF FF FF FF FF FF FF (高)
0xFF FF 7F FF FF FF FF FF - 0xFF FF FF FF FF FF FF FF (自分で計算してください)

ユーザー 128T: 0x00 00 00 00 00 00 00 00 - 0x00 00 7F FF FF FF FF FF (下位)
0x00 00 80 00 00 00 00 00 00 - 0x00 00 80 00 00 00 00 00 (自分で計算してください)

0x00 00 7F FF FF FF FF FF == 127T
質問: 64 ビット システムの境界線は 128T ですか? 127T ですか?

アクセス権

プロセスがユーザー モードにある場合、ユーザー空間メモリにのみアクセスできます。カーネル モードに入った後にのみ、カーネル空間メモリにアクセスできます。

PAE メカニズム

CPU ビット幅とは、CPU が 1 クロック サイクル内で処理できるバイナリ ビットの数を指します。通常のシナリオでは、32 ビット システム CPU のアドレス バスは 32 ビットです。ただし、PAE メカニズムの導入後は、16 ビット CPU のアドレス バス ビット幅は 20 ビット (物理メモリ 1M)、32 ビット CPU のアドレス バスは 36 ビット (物理メモリ 64GB)、64 ビット CPU のアドレス バス ビット幅は 40 ビット (物理メモリ 1TB) になります。したがって、32 ビット システムは最大 4 GB のメモリ スティックのみをサポートすると単純に言うことはできません。

4. デバッグ

プログラム登録

cs: コードセグメントレジスタ
ds: データセグメントレジスタ
ss: スタックセグメントレジスタ
es: 拡張セグメントレジスタ
fs: 32ビット後のフラグセグメントレジスタ
gs: 32ビット後のグローバルセグメントレジスタ

カーネルクラッシュログの例:

RIP: 0010:[ ] [ ] xxxxxxxxxx+0x69/0x70
RSP: 0018:ffff886241737d98 EFLAGS: 00010246
RAX: ffff880034814d40 RBX: ffff881fc6248740 RCX: 00000000000000200
RDX: 0000000000000000 RSI: 0000000000000286 RDI: ffff881fc6381858
RBP: ffff886241737d98 R08: ffff886241734000 R09: 0000000000000000
R10: ffff880034814d40 R11: 00000000000000200 R12: ffff881fc62487a0
R13: 00000000000000000 R14: 00007fff86cb6260 R15: ffff881fc6381858
FS: 00007f78b59b8720(0000) GS:ffff885ffe3c0000(0000) knlGS:0000000000000000
CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: 00007f690a057180 CR3: 0000006208985000 CR4: 00000000003627e0
DR0: 00000000000000000 DR1: 0000000000000000 DR2: 00000000000000000
DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 00000000000000400

プログラムレジスターの表示

GDB を使用して Linux 32 ビット上の ELF32 実行可能ファイルをデバッグし、info r コマンドを使用してレジスタの状態を確認します。

セグメント レジスタには 0x23 と 0x2b の 2 つのケースがあります。

16進数: 0023
バイナリ: 0000000000100 0 11 - セグメント番号: 4 - テーブルタイプ: GDT - 特権レベル: Ring3
16進数: 002B
バイナリ: 0000000000101 0 11 - セグメント番号: 5 - テーブルタイプ: GDT - 特権レベル: Ring3

セグメント番号: 4ビット目から始まる テーブルタイプ: 3ビット目 特権レベル: 1ビット目と2ビット目

Linux で GDT を直接表示するコマンドやツールが見つからなかったので、ソース コードを調べて答えを見つけました。

これら 2 つの項目によって記述されるセグメントは Windows と同じで、ベース アドレスは 0、サイズは 4 GB です。

Windows と Linux はどちらも、この方法で CPU のセグメント化されたメモリ管理メカニズムをバイパスすることを選択します。

ただし、これは両方のオペレーティング システムに当てはまるものの、セグメント メカニズムが完全に使用されていないことを意味するわけではないことに注意してください。CPU のタスク管理 TSS は引き続き使用する必要があります。誰もがこれを知っておく必要があります。セグメンテーション メカニズムは Linux 64 ビット システムでは歓迎されませんが、オペレーティング システムは引き続き、最初にセグメンテーションを行ってからページングを行うというアドレス指定方法を維持します。

結論

Linux のメモリ管理とアドレス指定に関するこの記事はこれで終わりです。Linux のメモリ管理とアドレス指定の詳細については、123WORDPRESS.COM の以前の記事を検索するか、以下の関連記事を引き続き参照してください。今後とも 123WORDPRESS.COM をよろしくお願いいたします。

以下もご興味があるかもしれません:
  • Linuxカーネルのメモリ管理アーキテクチャの詳細な説明
  • Linux のメモリ管理メカニズムの詳細な分析
  • Linux 管理者ガイド (4) -- メモリ管理

<<:  ドラッグ効果を実現するための純粋なCSSコード

>>:  HTML+CSSプロジェクト開発経験概要(推奨)

推薦する

VMware マルチノード環境を構成する方法

このチュートリアルでは CentOS 7 64 ビットを使用します。各仮想マシンに 2GB のメモリ...

MySQL 8.0.13 で日付を 0000-00-00 00:00:00 に設定すると発生する問題を解決する

データベース操作を学び始めたばかりです。今日、データを保存していたところ、エラーが発生していることに...

Vueオプションの詳細な説明

目次1. オプションとは何ですか? 2. 含まれる属性3. エントリー属性エルデータ方法コンポーネン...

ウェブサイト標準の検証方法を通じてFlashページを共有する方法

1. 埋め込みは違法です<embed> タグは Netscape のプライベート タグで...

DockerにRedisコンテナをインストールするための実装手順

目次DockerにRedisをインストールする1. Redisイメージを見つける2. Redisイメ...

純粋な CSS でカスタムラジオボタンとチェックボックス機能を実装する

1. 効果を達成する 2 知識ポイント2.1 <label> タグHTML では、<...

角度でechartsマップを使用する詳細な説明

目次echartの初期化アプリベースチャートコンポーネントhtml CS app-base-char...

MySQL マルチテーブルクエリの具体例

1. SELECT句を使用して複数のテーブルをクエリするSELECT フィールド名 FROM tab...

遭遇したいくつかのブラウザ互換性の問題について簡単に説明します

背景ブラウザの互換性の問題を解決するのは非常に面倒なことです。高度な技術はそれほど必要ありませんが、...

mysql5.7.19 winx64 解凍版のインストールと設定のチュートリアル

mysql 5.7.19 winx64解凍版のインストールチュートリアルを収録しました。具体的な内容...

Dockerはターミナルで中国語を入力できない問題を解決します

序文:ある日、DockerでMySQLサービスを構築したところ、MySQLのコマンドラインで中国語の...

HTML フォーマットの json のサンプルコード

さっそく、コードを直接投稿します。具体的なコードは次のとおりです。 <!DOCTYPE htm...

ドメイン名を nginx サービスにバインドする方法

nginx.conf で複数のサーバーを設定します。 http リクエストを処理する際、nginx ...

レスポンシブ Web デザイン手法を実装し、ウォーターフォール モデルに別れを告げる 5 つのステップ (グラフィック チュートリアル)

次の Web デザイン プロジェクトはレスポンシブにする必要があると上司をようやく納得させることがで...

Nginx で WordPress を設定する方法

以前、私は自分で WordPress を構築していましたが、当時はサードパーティの仮想ホストを使用し...