Linux のメモリ管理 | 2. 仮想アドレス空間のレイアウト

画像
私のサークル: シニア エンジニアが集まる場所
私はシニア組み込みソフトウェア開発エンジニア、ブラザー ドンです。組み込み Linux ドライバー開発とシステム開発に従事しており、フォーチュン 500 企業で働いた経験があります。
クリエイティブ哲学: 誰もが読書から何かを得ることができるように、高品質の埋め込み記事を共有することに重点を置きます。
画像
画像

前の章では、メモリ管理の起源と中心となる考え方について学びました。まず、仮想メモリ空​​間の管理を順番に紹介しましょう。Linux

 

同様に、Linuxカーネルが仮想メモリ空​​間を抽象化するのは、主に各プロセスがその空間を排他的に利用できるようにするためです。では、仮想メモリ空​​間はどのようにレイアウトされるのでしょうか?

前提: 桁が異なるとCPU、アドレス指定機能も異なり、抽象化された仮想メモリ空​​間のサイズも異なります。共通の Take を使用します。 32 ビットCPU を例として挙げます。

 

1. 仮想メモリ空​​間のレイアウト

32 ビットの場合、アドレス指定範囲は 、つまり 、つまり まで抽象化された仮想メモリ空​​間です。 CPU0~2^320x00000000-0xFFFFFFFF4G

この4GBメモリ空間はユーザー空間とカーネル空間Linux a> は次のようなカーネル空間です:、合計 はユーザー スペース、、合計 に分割されます。 、うち 0x0000000-0xBFFFFFFF3G0xC00000000-0xFFFFFFFF1G

画像-20230924173124939

カーネル空間またはユーザー空間に関係なく、仮想メモリ空​​間に基づいて分割されており、その直接アクセスは依然として物理アドレスではなく仮想アドレスです。

コードを記述した後、生成された実行可能プログラムは実行後にシステム プロセスになります。「仮想」の観点から見ると、各プロセスはこの< a i=1>仮想アドレス空間を排他的に使用します。 、4G

 

2. ユーザー空間のレイアウト

前述したように、ユーザー空間は、 のサイズの仮想メモリ内の 0x0000000-0xBFFFFFFF に分散されます。 3G

各ユーザー プロセスは、一貫したアクセス属性を持つアドレス空間が一緒に保存されるという原則に従って 5 つの異なるメモリ領域に分割されます。一貫したアクセス属性参照: 読み取り可能、書き込み可能、​​実行可能):

  • コード セグメント:Text Segment。これはバイナリ プログラムです。コード セグメントは実行時に不正に変更されないようにする必要があります。< a i=3>このセクションは読み取り専用です
  • データ セグメント:Data Segment、主に静的変数とグローバル変数を含む初期化された変数を格納します。このセクションは読み取りおよび書き込み可能です。
  • BSS セクション:BSS Segment は、主に初期化されていないグローバル変数を保存します。メモリ内では、すべての bss セクションは次のように設定されます。ゼロ。このセクションは読み取りおよび書き込み可能です。
  • ヒープ セグメント:Heap Segment は、主にプロセスの実行中に動的に割り当てられるメモリ セグメントを保存します。サイズは固定されておらず、動的に変更できます。通常、 mallocfree を使用して割り当てと解放を行い、ヒープの増加方向は上向きになります。
  • ファイル マッピング セグメントと匿名マッピング セグメント:Memory Mapping Segment は、主にプロセスまたは依存するダイナミック ライブラリによって使用されるファイルを格納し、低いアドレスから上に向かって増加します。
  • スタック セグメント:Stack Segment。主にプロセスによって一時的に作成されたローカル変数、関数呼び出しコンテキスト情報などが格納され、スタックは下方に向かって成長します。 。

画像-20231005160139650

実行可能プログラムの場合、size コマンドを使用して、コード セグメント、データ セグメント、その他のデータ情報を含むコンパイルされた実行可能ファイルのサイズを次のように表示できます。< /span>

donge@Donge:$ size Donge-Demo
   text    data     bss     dec     hex filename
  12538    1916   43632   58086    e2e6 Donge-Demo
  • text:コードセグメントサイズ
  • data:データセグメントサイズ
  • bssbss段大小
  • dec: 実行可能ファイルのサイズ (10 進数)
  • hex: 実行ファイルサイズ(16進数)

 

プログラムの実行後、cat /proc/PID/maps コマンドまたは pmap PID コマンドを使用して、仮想メモリ空​​間内のプロセスの割り当てを表示できます。 PID は、次のようなプロセスの PID 番号です。

donge@Donge:$ cat /proc/16508/maps
55976ff9e000-55976ffa0000 r--p 00000000 08:10 184922                     /home/donge/WorkSpace/Program/Donge_Programs/Donge_Demo/build/Donge-Demo
55976ffa0000-55976ffa2000 r-xp 00002000 08:10 184922                     /home/donge/WorkSpace/Program/Donge_Programs/Donge_Demo/build/Donge-Demo
55976ffa2000-55976ffa3000 r--p 00004000 08:10 184922                     /home/donge/WorkSpace/Program/Donge_Programs/Donge_Demo/build/Donge-Demo
55976ffa3000-55976ffa4000 r--p 00004000 08:10 184922                     /home/donge/WorkSpace/Program/Donge_Programs/Donge_Demo/build/Donge-Demo
55976ffa4000-55976ffa5000 rw-p 00005000 08:10 184922                     /home/donge/WorkSpace/Program/Donge_Programs/Donge_Demo/build/Donge-Demo
55976ffa5000-55976ffaf000 rw-p 00000000 00:00 0
559771d91000-559771db2000 rw-p 00000000 00:00 0                          [heap]
7fec1ad84000-7fec1ad87000 rw-p 00000000 00:00 0
7fec1ad87000-7fec1adaf000 r--p 00000000 08:10 22282                      /usr/lib/x86_64-linux-gnu/libc.so.6
7fec1adaf000-7fec1af44000 r-xp 00028000 08:10 22282                      /usr/lib/x86_64-linux-gnu/libc.so.6
7fec1af44000-7fec1af9c000 r--p 001bd000 08:10 22282                      /usr/lib/x86_64-linux-gnu/libc.so.6
7fec1af9c000-7fec1afa0000 r--p 00214000 08:10 22282                      /usr/lib/x86_64-linux-gnu/libc.so.6
7fec1afa0000-7fec1afa2000 rw-p 00218000 08:10 22282                      /usr/lib/x86_64-linux-gnu/libc.so.6
7fec1afa2000-7fec1afaf000 rw-p 00000000 00:00 0
7fec1afb5000-7fec1afb7000 rw-p 00000000 00:00 0
7fec1afb7000-7fec1afb9000 r--p 00000000 08:10 22068                      /usr/lib/x86_64-linux-gnu/ld-linux-x86-64.so.2
7fec1afb9000-7fec1afe3000 r-xp 00002000 08:10 22068                      /usr/lib/x86_64-linux-gnu/ld-linux-x86-64.so.2
7fec1afe3000-7fec1afee000 r--p 0002c000 08:10 22068                      /usr/lib/x86_64-linux-gnu/ld-linux-x86-64.so.2
7fec1afef000-7fec1aff1000 r--p 00037000 08:10 22068                      /usr/lib/x86_64-linux-gnu/ld-linux-x86-64.so.2
7fec1aff1000-7fec1aff3000 rw-p 00039000 08:10 22068                      /usr/lib/x86_64-linux-gnu/ld-linux-x86-64.so.2
7ffce385d000-7ffce387e000 rw-p 00000000 00:00 0                          [stack]
7ffce394e000-7ffce3952000 r--p 00000000 00:00 0                          [vvar]
7ffce3952000-7ffce3953000 r-xp 00000000 00:00 0                          [vdso]

上記は、プロセスのコードセグメント、ヒープ、ファイルマッピングセグメント、スタックメモリの分布などを大まかに見ることができます. 上記は、実行可能プログラムがメモリにロードされた後のユーザーモードの仮想メモリ空​​間のレイアウトです。

 

ところで、私のサークルを紹介させていただきます。先輩エンジニアの集いの場です。皆様のご参加をお待ちしております。

3. カーネル状態空間のレイアウト

カーネル状態の仮想空間レイアウトを見てみましょう。まず次のことを知る必要があります。

  1. Linuxシステムでは、ユーザー プロセスは通常、ユーザー空間の仮想アドレスにのみアクセスでき、インライン オペレーションまたはシステム コールを実行する場合にのみカーネル空間にアクセスできます。
  2. すべてのプロセスがシステム コールを通じてカーネル状態に入ると、同じ仮想アドレス空間が表示され、カーネル状態の仮想メモリ空​​間を共有します。

 

32 ビットのカーネル状態の仮想空間は、 のサイズで仮想メモリ内の0xC00000000-0xFFFFFFFF に分散され、次のように分割されます。エリア1G

  • ダイレクト マッピング エリア (Direct Memory Region): 名前が示すように、ダイレクト マッピング エリアは、物理的なマッピング エリアと 1 対 1 のマッピング関係を直接確立します。メモリ。カーネル空間の先頭アドレスから896Mまでのカーネル空間アドレス範囲はダイレクトメモリマッピング領域であり、この領域のリニアアドレスと割り当てられた物理アドレスは連続しています。

896M上記のカーネルアドレス空間は、ハイエンドメモリ領域とも呼ばれます。

  • セキュリティ保護ゾーン: 8M のサイズのメモリ ホールにもなります。その主な目的は、不連続な領域への不正なアクセスを回避することです。エリア。 a>

  • 動的マッピング領域: vmalloc Region、この領域は Vmalloc 関数によって割り当てられ、その特徴は次のとおりです。 仮想アドレス 空間は連続していますが、物理アドレス空間は必ずしも連続しているとは限りません。

  • 永続マッピング領域 (Persistent Kernel Mapping Region): この領域は主にハイエンド メモリへのアクセスに使用され、< i=3> インターフェイスのハイエンド メモリ ページでは、 関数を使用して、割り当てられたハイエンド メモリをこの領域にマップできます。 alloc_page (_GFP_HIGHMEM)kmap

  • 固定マッピング領域 (Fixing kernel Mapping Region): この領域の仮想メモリ アドレスは、物理メモリの上位アドレスに自由にマッピングできます。 「固定」とは「仮想メモリ空​​間のアドレスが固定である」という表現であり、マッピングされる物理アドレスは可変である。

なぜ固定マッピングという概念があるのでしょうか?

たとえば、カーネルの起動プロセス中に、一部のモジュールは仮想メモリを使用し、それを指定された物理アドレスにマップする必要がありますが、これらのモジュールがアドレス マッピングを実行する前に完全なメモリ管理モジュールが初期化されるのを待つ方法はありません。したがって、カーネルはいくつかの仮想アドレスを固定的に割り当てており、これらのアドレスには固定の目的があり、このアドレスを使用するモジュールは、初期化中にこれらの固定的に割り当てられた仮想アドレスを指定された物理アドレスにマッピングします。

画像-20231005155942462

4. まとめ

上記は仮想アドレス空間全体の分割であり、要約すると次のようになります。

画像-20231005160802093

いいね + フォローで迷子になりません

画像
ドン兄弟オリジナルの公式アカウントと Planet [Embedded Art] をフォローすることを歓迎します!

おすすめ

転載: blog.csdn.net/dong__ge/article/details/133782500